11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravel 7.xで初めてアプリケーションを作ってみる。その1 SNS認証

Last updated at Posted at 2020-05-09

はじめに

Laravelを知らない中級(中年)プログラマーがマイグレーションファイルの仕組みを調べてみたけど全くわからない という記事がまだ途中なのですが、せっかく少しだけLaravelのことがわかってきたので小さなアプリケーションでも作ってみようと思います。

前提

僕は「Laravel」はクイックスタートを数回読んだくらいで全く利用経験がありません。普段から使ってる方からしたら見当違いな事を書くかもしれません。
この記事の対象は PHP 中級者でLaravel未経験者及び初心者を想定しています。PHPの基礎的なシンタックスの説明とかは割愛しますのでご了承ください。
今回は認証がテーマですが、 Laravel Socialite の説明を読んでその通りに組んでみただけです。ソースも追っていませんしリクエストやレスポンスもチェックしていません。本格運用に使った際の事故などの保証はしません!ご了承ください☆

環境

Laravel Framework 7.2.0
PHP 7.3.15

さぁ行ってみよう!

今回の内容は こことかこことか を読みながらその通りにやってみたという感じのものです。WEBにもlaravelのSNS認証の記事はいっぱいありますので目新しいものでもないのですが、7.x系でやっている記事はまだあまり見かけません。あと、たいていSNS1種類の説明で済ませているところが多いので、やってみたサービス全部のせておきますね。中級者対象ですので composer のインストールの説明とかは割愛させていただきます。

Laravel環境を作ろう

さて、初めてのLaravelのアプリケーションを作ってみます。チュートリアルはやってみましたが目的を持って触るのは初めてです。ワクワクしますね。
とりあえず、公式のインストールの説明 を見ながら環境を作ってみましょう。

適当なワークディレクトリに移動してこんな感じ。

$ laravel new myApp

...略...

Package manifest generated successfully.
Application ready! Build something amazing.

これでオッケーだそうです。簡単ですね!素晴らしい。
組込み開発サーバも用意されているようです。
プロジェクトディレクトリに移動してサーバを動かしてみましょう。
デフォルトポートは8000らしいのですが、いろいろ動かしているので8899あたりを指定してみます。

$ cd myApp
$ php artisan serve --port=8899

http://localhost:8899/ にアクセスしてみます。

スクリーンショット 2020-05-06 18.28.48.png

これで Laravel環境ができあがりです!サクサクですね☆

認証の準備

さて、認証の下準備です。
Laravel6 までは php artisann make:auth というコマンドで認証の基本的なセットアップをしていたらしいのですが、Laravel7 からは laravel/ui というのに組み込まれたそうです。
ドキュメント によると、

LaravelはJavaScriptやCSSプリプロセッサの使用を規定してはいませんが、開発時点の元としてほとんどのアプリケーションで役立つだろうBootstrapやReact、Vueを提供しています。これらのフロントエンドパッケージをインストールするため、LaravelはNPMを使用しています。

とのことです。よく使うライブラリがすでに準備されていてコマンドを叩くだけでベースが出来てしまうみたいです。VueもReactもチャチャッとセッティング出来るっぽい?楽しそうですね。今回はさわりませんが、そのうちこの辺やってみます。

で、認証は laravel/ui--auth パラメータを付けて用意するっぽいです。
まずは、 laravel/ui をインストールしてその後にartisanコマンドを叩く。
こんな感じ?

$ composer require laravel/ui 

...略...

Package manifest generated successfully.
30 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

$ php artisan ui vue --auth

...略...

Vue scaffolding installed successfully.
Please run "npm install && npm run dev" to compile your fresh scaffolding.
Authentication scaffolding generated successfully.

$ npm install && npm run dev

...略...

 DONE  Compiled successfully in 6544ms                                           6:47:04 PM

       Asset     Size   Chunks             Chunk Names
/css/app.css  177 KiB  /js/app  [emitted]  /js/app
  /js/app.js  1.4 MiB  /js/app  [emitted]  /js/app
スクリーンショット 2020-05-06 18.48.15.png

あっという間にログインフォームが用意できてしまいましたね。
Bootstrap感が強すぎてアレな感じですが、とりあえずはまぁいいでしょう。

データベース接続設定

LaravelはMySqlがデフォルトになっているのですが、今回はちょっと作りたいものの事情でSQLite3を使おうと思います。環境設定ファイルを変更します。
.env ファイルをこんな感じに書き換えてしまいます。

.env
DB_CONNECTION=sqlite
#DB_CONNECTION=mysql
#DB_HOST=127.0.0.1
#DB_PORT=3306
#DB_DATABASE=laravel
#DB_USERNAME=root
#DB_PASSWORD=

接続設定を変更したら、組込み開発サーバを再起動しておきます。「Control+C」で止めて以下のコマンドを叩きます。

$ php artisan serve --port=8899

SQLite 3 データベースファイルの作成

接続設定を書き換えた時に、データベースパスを指定していませんでしたね。無指定だと PROJECT_ROOT/datebase/database.sqlite を参照するそうです。もし指定したい場合は .env を良しなにどうぞ。
データベースファイルを作ります。

$ sqlite3 database/database.sqlite
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.

sqlite> .table
sqlite> .q

これで空のデータベースファイルができました。

マイグレーションの実行

Laravelにはデータベース管理用にマイグレーションが用意されています。
SQLite3はいまいちこのマイグレーションの機能が使いにくいみたいなのですが、初期化するために使ってみます。

$ php artisan migrate

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0 seconds)

何個かテーブルが出来たようですね。
ここには出力されてないですが、migrationssqlite_sequenceというデータベース管理履歴用のテーブルも出来てます。

通常認証

ユーザーテーブルが出来ていますので、通常認証がもうできそうな雰囲気ですね。試してみましょう。
ブラウザの右上に 「Register」 というリンクがありますのでそこから登録画面に飛びます。
URIは http://localhost:8899/register こんな感じだと思います。

スクリーンショット 2020-05-06 20.12.14.png

登録フォームの「Register」ボタンを押下すると、ダッシュボードに遷移しました。

スクリーンショット 2020-05-06 20.42.20.png

通常認証があっという間に用意できましたね。便利ですねぇ。

Usersテーブルにカラム追加

SNS認証のためにデフォルトのUsersテーブルの構造を少し変更します。
SNSが提供するOAuthの中にはemail情報が返ってこないものもあるとのことで、nullを受け入れるようにします。また、SNS認証にはパスワードという概念自体ありません。カラム自体を削除するか悩むところですが、とりあえずnullを受け入れるようにします。追加カラムとしてSNS名とSNSで割り振られたID、あと面白いところでアバター画像を大抵のSNSから取得できるようなのでそれも格納することにします。
以下のようなイメージ。

    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
    "name" VARCHAR(255) NOT NULL COLLATE BINARY
    "email_verified_at" DATETIME DEFAULT NULL
    "remember_token" VARCHAR(255) DEFAULT NULL COLLATE BINARY
    "created_at" DATETIME DEFAULT NULL
    "updated_at" DATETIME DEFAULT NULL
-   "email" VARCHAR(255) NOT NULL COLLATE BINARY
-   "password" VARCHAR(255) NOT NULL COLLATE BINARY
+   "email" VARCHAR(255) DEFAULT NULL COLLATE BINARY
+   "password" VARCHAR(255) DEFAULT NULL COLLATE BINARY
+   "avatar" VARCHAR(255) DEFAULT NULL COLLATE BINARY
+   "social_name" VARCHAR(255) NOT NULL COLLATE BINARY
+   "social_id" VARCHAR(255) NOT NULL COLLATE BINARY

では、migrationファイルを用意します。
Laravelのマイグレーションでカラム属性を変更する場合はcomposerで doctrine/dbal を追加する必要があるそうです。

$ composer require doctrine/dbal

...略...

Package manifest generated successfully.
31 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

入りました。マイグレーションファイルの生成をします。

$ php artisan make:migration prepare_users_table --table users
Created Migration: 2020_05_06_122609_prepare_users_table

生成されたマイグレーションファイルを編集します。

$ vim database/migrations/2020_05_06_122609_prepare_users_table.php

※ タイムスタンプは生成時のものになります。

database/migrations/2020_05_06_122609_prepare_users_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class PrepareUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('email')->nullable()->change();
            $table->string('password')->nullable()->change();
            $table->string('avatar')->nullable();
            $table->string('social_name', 255)->nullable();
            $table->string('social_id', 255)->nullable();
            $table->dropIndex('users_email_unique');
        });
        Schema::table('users', function (Blueprint $table) {
            $table->string('social_name')->nullable(false)->change();
            $table->string('social_id')->nullable(false)->change();
        });

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
}

down() を書いていません。LaravelのマイグレーションはSQLite使用時に、一つのマイグレーションによる複数カラム削除/変更はサポートされてないそうです。(くわしくはこちら)。本格運用時にマイグレーションでデータベースを管理する場合は、しっかりと手順を踏んだほうが良いですが、この記事では冗長になりすぎるのでロールバックは割愛します。
Larabelのデフォルトで生成された通常認証では email のカラムにインデックスが貼ってありユニークになっています。今回は別のSNSから戻り値として同じemailが返ってくる可能性があるのでユニークインデックスを削除します。
social_namesocial_idNOT NULLにしたいのですが、すでにあるテーブルにカラムを追加する時にいきなりNOT NULLのものを追加はできないのでnullableで追加した後にNOT NULLに変更しています。
migrationファイルの編集を終えたら実行の準備です。
追加カラムがNOT NULLなので、先程 Register フォームから登録してしまったデータを削除しておきます。

$ sqlite3 database/database.sqlite
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
sqlite> DELETE FROM USERS;
sqlite> VACUUM;
sqlite> .q

テーブルレコードの削除を終えたら migration コマンドを叩きます。

$ php artisan migrate
Migrating: 2020_05_06_122609_prepare_users_table
Migrated:  2020_05_06_122609_prepare_users_table (0.06 seconds)

テーブル設計更新はこれで完了です。テーブル構造がこれで良いのか、インデックスは等いろいろと無いわけではないですが、とりあえずSNS認証を実装するのが今回の目的なので次に行きます。

Socialite のインストール

いよいよSNS認証の実装です。実装と言ってもロジックは Laravel Socialite に全部任せてしまいます。では、composerでSocialiteをインストールしましょう。

$ composer require laravel/socialite
Package manifest generated successfully.
31 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

とりあえずこれでSNS認証の下準備は終わりです。設定をしていきましょう!

実装の計画

今回は以下の4つのサービスで認証を実現したいと思います。

  • Twitter
  • facebook
  • Google
  • GitHub

設定が必要なファイルは以下です。

PROJECT_ROOT
├ .env
├ app
│ ├ User.php
│ └ Http
│   └ Controllers
│     └ Auth
│       └ LoginController.php
├ config
│ └ services.php
├ resources
│ └ views
│   └ auth
│     └ login.blade.php
└ routes
  └ web.php

全部設定し終わらないと動きませんので順序考えずに上からサクサク見ていきます。

/.env

環境設定ファイルですね。以下を追記します。

/.env
TWITTER_CLIENT_ID=Twitterから取得したID
TWITTER_CLIENT_SECRET=Twitterから取得したKEY
TWITTER_CALLBACK_URL="https://my-domain.com/login/twitter/callback"

FACEBOOK_APP_ID=facebookから取得したID
FACEBOOK_APP_SECRET=facebookから取得したKEY
FACEBOOK_CALLBACK_URL="https://my-domain.com/login/facebook/callback"

GOOGLE_CLIENT_ID=Googleから取得したID
GOOGLE_CLIENT_SECRET=Googleから取得したKEY
GOOGLE_CALLBACK_URL="https://my-domain.com/login/google/callback"

GITHUB_CLIENT_ID=GitHubから取得したID
GITHUB_CLIENT_SECRET=GitHubから取得したKEY
GITHUB_CLIENT_CALLBACK="https://my-domain.com/login/github/callback"

代入値のIDとKEYは各種サービスから割り当てられたものを記述します。
取得方法は長くなるので、この記事の末尾に一つずつ紹介します。
コールバックURIのドメインはご自分の環境に合わせて設定するのですが、httpsでないとだめなサービスもあった気がします。ローカル環境で構築したい場合は以下のような感じです。

GITHUB_CLIENT_CALLBACK="http://localhost:8899/login/github/callback"

ポートは環境に合わせてください。ただ、localhostで実装が難しいサービスもあります。もしローカル環境で試したい場合はLravelの公式で紹介しているようにGitHubでまずは試してみるのがおすすめです。GitHubはさすが開発の事情をわかっているのか localhost での実装がやりやすくなっているようです。
定数名がFACEBOOKだけAPPなのがちょっと迷ったのですが、まぁいいでしょう。

/app/User.php

Laravel触るのが初めてなのでしっかり理解しているわけではないのですが、EloquentModelの$fillableに更新したいカラムを登録するのがお約束みたいです。マイグレーションでテーブル構造変更をしましたので、取り扱いたい情報を追記しておきましょう。

    protected $fillable = [
-       'name', 'email', 'password',
+       'name', 'email', 'password', 'social_name', 'social_id', 'avatar',
    ];

/app/Http/Controllers/Auth/LoginController.php

このファイルがこの記事の肝ですね。このクラス以外は要するに設定だけですしね。
以下の2メソッドを追記します。

/app/Http/Controllers/Auth/LoginController.php
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\DB;
use Socialite;
use App\User;

......

    /**
     * 各SNSの認証ページヘリダイレクト
     *
     * @param string $social sns service name.
     * @return \Illuminate\Http\Response
     */
    public function redirectToProvider($social)
    {
        return Socialite::driver($social)->redirect();
    }

    /**
     * 各SNSから返されるユーザー情報を処理
     *
     * @param string $social sns service name.
     * @return \Illuminate\Http\Response
     */
    public function handleProviderCallback($social)
    {
        if (!in_array($social, ['github', 'facebook', 'google', 'twitter'], true)) {
            return redirect()->to('/home');
        }
        try {
            $socialAccount = $social == 'twitter' ?
                Socialite::driver($social)->user() :
                Socialite::driver($social)->stateless()->user();
        } catch (\Exception $e) {
            return redirect('/home');
        }
        $where = [
            ['social_name', '=', $social],
            ['social_id', '=', $socialAccount->getId()]
        ];
        $userName = $socialAccount->getNickname() ?? $socialAccount->getName();
        $countUser = DB::table('users')->where($where)->count();

        if ($countUser === 1) {
            ($user = User::where($where)->first())
                ->update([
                    'name' => $userName,
                    'email' => $socialAccount->getEmail(),
                    'avatar' => $socialAccount->getAvatar(),
                ]);
        } else {
            ($user = new User([
                'name' => $userName,
                'email' => $socialAccount->getEmail(),
                'social_name' => $social,
                'social_id' => $socialAccount->getId(),
                'avatar' => $socialAccount->getAvatar(),
            ]))->save();
        }

        auth()->login($user, true);
        return redirect()->to('/home');
    }

......

(@Xyasya さんのご指摘で修正いたしました。ありがとうございます。2020.07.01)

上から読んでいきましょう。

redirectToProvider()

引数として受け取った文字列をSocialiteクラスのstaticメソッドのdriver()に引数として渡します。Socialiteクラスは渡された引数、つまりSNS名と相応のプロバイダークラスを戻します。その後、メソッドチェーンで戻ってきたプロバイダークラスのredirect()メソッドをコールしています。
この引数$socialはルート定義でURIから渡されるように設計します。
やっていることは見ただけでなんとなくはわかりますね。

handleProviderCallback()

redirectToProvider()で指定されたSNSでOAuth認証処理を終え、戻ってきたらこのメソッドが叩かれます。
引数としてコールバックURIから取得したSNS名が渡されるので一応念の為ホワイトリストでフィルタしておきます。
Sociarite::driver()の戻り値のuser()メソッドをコールします。おそらく認証が失敗すると例外InvalidStateExceptionが返ってくるのでそれをキャッチする前提なのでしょう。例外の場合は/にリダイレクトで跳ね返します。
今回のSNS4つのうちtwitterだけ仕様が違うので三項演算子で切り分けます。
あとは、データベースに指定したSNS名、SNSIDがあればそれを、なければレコードを登録しログイン処理し/homeにリダイレクトという感じです。簡単ですね。

/config/services.php

これは先に見たほうが早いですね。
以下を配列の末尾に追加します。

/config/services.php
    'github' => [
        'client_id' => env('GITHUB_CLIENT_ID'),
        'client_secret' => env('GITHUB_CLIENT_SECRET'),
        'redirect' => env('GITHUB_CLIENT_CALLBACK'),
    ],

    'facebook' => [
        'client_id' =>  env('FACEBOOK_APP_ID'),
        'client_secret' => env('FACEBOOK_APP_SECRET'),
        'redirect' =>  env('FACEBOOK_CALLBACK_URL'),
    ],

    'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect' => env('GOOGLE_CALLBACK_URL'),
    ],

    'twitter' => [
        'client_id' => env('TWITTER_CLIENT_ID'),
        'client_secret' => env('TWITTER_CLIENT_SECRET'),
        'redirect' => env('TWITTER_CALLBACK_URL'),
    ],

最初に.envで設定したものをそのまま追加しているだけですね。
説明はいらないと思います。

/resources/views/auth/login.blade.php

ログイン用テンプレートファイルですね。
いろいろ書いてありますが、ざっくり削除してボタンだけにしちゃいましょう。
ボタンと言っても見た目だけで単なる Aタグでリンクを貼っているだけですね。
URIは次で定義するルーティングのものです。

/resources/views/auth/login.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <a class="btn btn-primary" href="/login/twitter">twitter</a>
                    <a class="btn btn-primary" href="/login/facebook">facebook</a>
                    <a class="btn btn-primary" href="/login/google">google</a>
                    <a class="btn btn-primary" href="/login/github">github</a>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

見た目やいろいろは、次の機会に触ってみたいと思います。今回はこれで我慢します。

/routes/web.php

これもまぁ、先に見てみましょう。
以下をルーティングファイルに追記します。

/routes/web.php
Route::get('login/{provider}', 'Auth\LoginController@redirectToProvider');
Route::get('login/{provider}/callback', 'Auth\LoginController@handleProviderCallback');

OAuth認証を実行するURIと認証後戻ってくるURIをルーティングしています。
{provicer}['github', 'facebook', 'google', 'twitter']のどれかが入り、その文字列が指定されたコントローラーのメソッドに引数として渡されるという流れですね。


実装は以上です!簡単ですね。ほぼ設定しかしてない印象です。
残るは各SNSでOAuth認証登録してIDとKEYをもらってくるだけです!
そこは別にいらないよーという方はお疲れ様です☆

各SNSのOAuth認証登録

各SNSの認証用のIDとKEYの取得のしかたです。わりとページのレイアウトデザインは変わるようなので、2020年5月現在の情報という感じです。見ていきましょう。

GitHub

まずは GitHub です。設定ページ https://github.com/settings/profile を開きます。
socialite-github-01.png
右上のプルダウンから Setting から入れます。
socialite-github-02.png
設定ページのプロフィールに遷移しますので、左のメニューから、開発者設定をクリックします。
socialite-github-03.png
開発者設定ページの左メニューから 「OAuth Apps」 をクリックします。
socialite-github-04.png
OAuth Appsのページを開き、右側にある緑色のボタン、「Register a new application」を押下します。socialite-github-05.png
アプリケーション情報登録フォームが表示されますので、必要事項を埋めて「Register application」ボタンを押下します。
特に問題のある項目はないと思います。
Authorization callback URL は当然先程設定した GitHub用のコールバックURLです。
socialite-github-06.png
Client IDClient Secret が発行されましたね。
これを、.env に記述すればオッケーです。

facebook

次は facebook です。イメージなのかもしれないですが、facebookは開発者用のページレイアウトやGUIが割と頻繁に変わる気がします。
参考になるといいのですが。。。
https://developers.facebook.com/
socialite-facebook-01.png
facebook開発者ページの右上、マイアプリプルダウンをクリックします。
socialite-facebook-02.png
プルダウンメニューから「アプリの作成」メニューを押下します。
socialite-facebook-03.png
アプリの表示名、連絡先メールアドレスを記入して「アプリIDを作成してください」ボタンを押下します。
socialite-facebook-04.png
ロボットではないよーチェックボックスをチェックして「送信」ボタンを押下します。
socialite-facebook-05.png
製品を追加画面で「Facebookログイン」を選択します。
socialite-facebook-06.png
アプリ・プラットフォームの選択で「ウェブ」を選択します。
socialite-facebook-07.png
有効なOAuthリダイレクトURIを記載して「変更を保存」ボタンを押下します。
他の設定は良しなにしてください。
socialite-facebook-08.png
「ウェブ」のタブでサイトURLを記載して「Save」ボタンを押下します。
socialite-facebook-09.png
アプリIDapp secret が発行されました。
facebookの場合、色々設定項目があり、どこからどこまでを入力しなくていはいけないか、いまいちわかりにくいところがあるのですが、とりあえず僕の環境では以上の設定でOAuth認証を実装できました。

Google

Google先生です。サービスによっては結構ニーズがあるかもしれませんね。
https://console.developers.google.com/project
開発者コンソールにアクセスします。
socialite-google-01.png
リソース管理で「プロジェクトを作成」を押下します。
socialite-google-02.png
新しいプロジェクトのプロジェクト名を入力して「作成」ボタンを押下します。場所は組織なしでも実装できました。
socialite-google-03.png
作成したプロジェクトの画面で左上のハンバーガーメニューから「APIとサービス > OAuth同意画面」を押下します。

socialite-google-04.png

OAuth同意画面で外部にチェックを入れて「作成」ボタンを押下します。場合によっては内部なんですかね。今回は深追いしません。
socialite-google-05.png
OAuth同意画面を生成するのに使う情報を登録します。
socialite-google-06.png
同意画面情報を登録したら、「認証情報を作成 > OAuthクライアントID」を押下します。
socialite-google-07.png
アプリケーションの種類は「ウェブアプリケーション」を選択し、アプリケーション名を入力。リダイレクトURIも登録してください。承認済みのJavaScript生成元は今回は未入力。「作成」ボタンを押下します。
socialite-google-08.png
OAuthクライアントのIDとシークレットが発行されました。

Googleのサービスは高機能でとてもありがたいのですが、GUIで迷子になることが多い気がします。僕だけですかね。

Twitter

最後にTwitterなんですが、ちょっと気をつけないとならない事があります。APIの使用許可の審査が割と厳しいらしく、「勉強のため」「実験で」「とりあえず使ってみたい」などだと弾かれます。しかも、一度弾かれるとその開発者アカウントでのAPI使用ができなくなり、再申請の方法もないようです。僕は一回「とりあえず触ってみたい」と申請してtwitterアカウント一つだめにしました。
とりあえず行ってみましょう。

https://apps.twitter.com/
socialite-twitter-01.png
まずは開発者アカウントを申請します。右上のAppから入ります。
socialite-twitter-02.png
Twitterの開発者ツールを使う理由はなんなの?と聞かれ選択する画面になります。
前回の反省から、いい子ですよ。ビジネスとして真剣に考えてますよをアピールするためにB2B製品を作るためと選択しました。
まぁ、何でも良いんでしょうけど、Twitter社を説得するつもりで選んだほうが良いかもです。
socialite-twitter-03.png
このTwitterアカウントであってる?と聞かれます。アカウントを切り替えたいなどあったらここで切り替えるんでしょう。オッケーで次に進みます。
socialite-twitter-04.png
組織情報を教えてよと聞かれます。出来る限りそれっぽいほうが良いと思います。ビジネスホームページなど持っていたらそれを記入したほうが良いかも。
socialite-twitter-05.png
TwitterのAPIをなんで使いたいの?と聞かれます。
今回は認証なんで、自社サービスの認証にTwitterのOAuth認証を使わせてほしいとかなんとか。いい子で真摯な姿勢をアピールします。英文で書かなければなりませんが、Google翻訳とかで大丈夫そうですね。
Twitterのデータを分析する?と聞かれます。マーケティング系のお仕事でAPIを使いたいなら、是非分析するにしたいと思うところですね。ただ、昨今の事情で政治関係やらなんやらでTwitter社的に都合の悪い使われ方をすることにかなり警戒しているっぽい感じです。全く予定がないなら「いいえ」にしたほうが良いかもしれません。
Twitterのツイートやリツイート、イイね等いろいろな機能を使いたい?と聞かれます。
せっかくだから使わせてほしいと言っておいたほうが良さそうです。が、真面目に使いたいんです、悪い事はしません!アピールが必要かも?
Twitterのデータを外部公開する?と最後に政府機関で利用する?と聞かれます。
うーん、これを「はい」にする場合はしっかりと理由を作っておいたほうが良いかもしれません。
次に進みます。
socialite-twitter-06.png
利用規約ですね。
同意して次に進みましょう。
socialite-twitter-07.png
申請が出来ました。確認メールが送信されているので、メールを受信したら「Confirm your email」のリンクを押下して申請完了しましょう。
このあと、申請内容に突っ込みどころがあると「そこんところどうなってるの?」とTwitter社からメールが来ます。英語で返信しないとなりません。僕も数回やり取りしたのですが、却下されました。結構そのパターンは辛いので、申請時に一発クリアを目指したほうが良いと思います。

管理者アカウントが取得できましたので早速アプリケーションを登録してみましょう。
socialite-twitter-13.png

初回にスクリーンショットを撮り忘れてしまい、すでにひとつアプリケーションがある状態です。
初回はレイアウトが違ったような気がします。
「Create an app」ボタンを押下します。

socialite-twitter-08.png

上から、アプリケーション名、アプリケーションの説明、APIを利用するURLと続きます。
ローカル環境からの呼び出しは出来ないようです。
ツイッター認証するかどうかのチェックボックスです。もちろんチェックします!
コールバックのURLは設定したものを記入します。
利用規約のURL、プライバシーポリシーのURL、組織名、組織URLと入力します。
ここは、可能な限りビジネスライクな情報を入れたほうが良いと思います。
最後にアプリケーションの使用方法を記入します。
英語で入力しなければなりませんが、Google翻訳で問題ありません。
内容はできる限り正直に真摯にビジネスライクに書きましょう!
「Create」ボタンを押下して次に進みます。
socialite-twitter-09.png
開発者規約です。
データの使い方やオートメーションツイートなどのルールについて書いてあります。
違反しないように気をつけましょう。
「Create」ボタンを押下することでアプリケーション登録の完了です。
socialite-twitter-10.png
アプリケーション情報です。
socialite-twitter-12.png
IDとキーが取得できました。

もう一点このままではTwitterでのOAuth認証時にコールバックにemail情報が返ってきません。
以下を設定しましょう。
socialite-twitter-11.png
下部の 「Request email address from users」 のチェックボックスをチェックします。

これで目標の4サービスのOAuth認証の実装が完了しました!
むしろ各SNSへの申請の方が大変でしたね。

コールバックで取得できるレスポンスについて

おまけです。
各SNSから戻ってくる情報について載せておきます。
参考にしていただけたら幸いです。

GitHub

  +token: "****************************************"
  +refreshToken: null
  +expiresIn: null
  +id: 12345678
  +nickname: "hideyukiMORI"
  +name: "HideyukiMORI"
  +email: "info@xion.cc"
  +avatar: "https://avatars0.githubusercontent.com/u/14159242?v=4"
  +user: array:31 [
    "login" => "************"
    "id" => 12345678
    "node_id" => "********************"
    "avatar_url" => "https://avatars0.githubusercontent.com/u/14159242?v=4"
    "gravatar_id" => ""
    "url" => "https://api.github.com/users/hideyukiMORI"
    "html_url" => "https://github.com/hideyukiMORI"
    "followers_url" => "https://api.github.com/users/hideyukiMORI/followers"
    "following_url" => "https://api.github.com/users/hideyukiMORI/following{/other_user}"
    "gists_url" => "https://api.github.com/users/hideyukiMORI/gists{/gist_id}"
    "starred_url" => "https://api.github.com/users/hideyukiMORI/starred{/owner}{/repo}"
    "subscriptions_url" => "https://api.github.com/users/hideyukiMORI/subscriptions"
    "organizations_url" => "https://api.github.com/users/hideyukiMORI/orgs"
    "repos_url" => "https://api.github.com/users/hideyukiMORI/repos"
    "events_url" => "https://api.github.com/users/hideyukiMORI/events{/privacy}"
    "received_events_url" => "https://api.github.com/users/hideyukiMORI/received_events"
    "type" => "User"
    "site_admin" => false
    "name" => "HideyukiMORI"
    "company" => "AYANE International Inc."
    "blog" => "hideyuki-mori.com"
    "location" => "Japan"
    "email" => "info@xion.cc"
    "hireable" => true
    "bio" => "Professional illustrator. Born in Tokyo in 1973. Graduated from Department of Japanese Painting, Musashino Art University. "
    "public_repos" => 2
    "public_gists" => 0
    "followers" => 0
    "following" => 0
    "created_at" => "2015-09-07T08:32:51Z"
    "updated_at" => "2020-05-09T12:48:29Z"

facebook

  +token: "*****************************************************************************************************************************************************************************************"
  +refreshToken: null
  +expiresIn: 1234567
  +id: "1234567890123456"
  +nickname: null
  +name: "森 秀之"
  +email: "xi@xion.cc"
  +avatar: "https://graph.facebook.com/v3.3/3303148003029667/picture?type=normal"
  +user: array:3 [
    "name" => "森 秀之"
    "email" => "xi@xion.cc"
    "id" => "1234567890123456"
  ]
  +"avatar_original": "https://graph.facebook.com/v3.3/3303148003029667/picture?width=1920"
  +"profileUrl": null

Google

  +token: "***************************************************************************************************************************************************************************"
  +refreshToken: null
  +expiresIn: 1234
  +id: "123456789012345678901"
  +nickname: null
  +name: "彩イラストレーター"
  +email: "**********@gmail.com"
  +avatar: "https://lh3.googleusercontent.com/a-/AOh14GjfWbBWspqJs6p5rtlb_D_2ToanTkkdDdkW29TNOw"
  +user: array:11 [
    "sub" => "123456789012345678901"
    "name" => "彩イラストレーター"
    "given_name" => "イラストレーター"
    "family_name" => "彩"
    "picture" => "https://lh3.googleusercontent.com/a-/AOh14GjfWbBWspqJs6p5rtlb_D_2ToanTkkdDdkW29TNOw"
    "email" => "**********@gmail.com"
    "email_verified" => true
    "locale" => "ja"
    "id" => "123456789012345678901"
    "verified_email" => true
    "link" => null
  ]
  +"avatar_original": "https://lh3.googleusercontent.com/a-/AOh14GjfWbBWspqJs6p5rtlb_D_2ToanTkkdDdkW29TNOw"

Twitter

  +token: "**************************************************"
  +tokenSecret: "*********************************************"
  +id: "1234567890"
  +nickname: "ayane_inc"
  +name: "彩音インターナショナル株式会社"
  +email: "*****@xion.cc"
  +avatar: "http://pbs.twimg.com/profile_images/1205169805948411905/E_tsyv7t_normal.jpg"
  +user: array:42 [
    "id_str" => "1234567890"
    "entities" => array:2 [
      "url" => array:1 [
        "urls" => array:1 [
          0 => array:4 [
            "url" => "https://t.co/UNrUdL5qX3"
            "expanded_url" => "https://www.youtube.com/channel/UCgARD8FD-VZFzRlFLgo4oAA?view_as=subscriber"
            "display_url" => "youtube.com/channel/UCgARD…"
            "indices" => array:2 [
              0 => 0
              1 => 23
            ]
          ]
        ]
      ]
      "description" => array:1 [
        "urls" => []
      ]
    ]
    "protected" => false
    "followers_count" => **
    "friends_count" => **
    "listed_count" => *
    "created_at" => "Thu Sep 05 18:27:31 +0000 2013"
    "favourites_count" => ***
    "utc_offset" => null
    "time_zone" => null
    "geo_enabled" => false
    "verified" => false
    "statuses_count" => ***
    "lang" => null
    "status" => array:24 [
      "created_at" => "Thu Apr 30 06:16:44 +0000 2020"
      "id" => 1234567890123456789
      "id_str" => "1234567890123456789"
      "text" => """
        RT @*************: 合皮コインケース | WakiWaki Party https://t.co/Kzi4qhJ6Vm @ayane_incさんから
        #AYANE_online
        """
      "truncated" => false
      "entities" => array:4 [
        "hashtags" => array:1 [
          0 => array:2 [
            "text" => "AYANE_online"
            "indices" => array:2 [
              0 => 84
              1 => 97
            ]
          ]
        ]
        "symbols" => []
        "user_mentions" => array:2 [
          0 => array:5 [
            "screen_name" => "*************"
            "name" => "*******"
            "id" => 1234567
            "id_str" => "1234567"
            "indices" => array:2 [
              0 => 3
              1 => 17
            ]
          ]
          1 => array:5 [
            "screen_name" => "ayane_inc"
            "name" => "彩音インターナショナル株式会社"
            "id" => 1234567890
            "id_str" => "1234567890"
            "indices" => array:2 [
              0 => 69
              1 => 79
            ]
          ]
        ]
        "urls" => array:1 [
          0 => array:4 [
            "url" => "https://t.co/Kzi4qhJ6Vm"
            "expanded_url" => "https://ayane.co.jp/product/coin-case_wakiwakiparty"
            "display_url" => "ayane.co.jp/product/coin-c…"
            "indices" => array:2 [
              0 => 45
              1 => 68
            ]
          ]
        ]
      ]
      "source" => "<a href="https://mobile.twitter.com" rel="nofollow">Twitter Web App</a>"
      "in_reply_to_status_id" => null
      "in_reply_to_status_id_str" => null
      "in_reply_to_user_id" => null
      "in_reply_to_user_id_str" => null
      "in_reply_to_screen_name" => null
      "geo" => null
      "coordinates" => null
      "place" => null
      "contributors" => null
      "retweeted_status" => array:23 [
        "created_at" => "Mon Apr 27 04:04:25 +0000 2020"
        "id" => 1234567890123456789
        "id_str" => "1234567890123456789"
        "text" => """
          合皮コインケース | WakiWaki Party https://t.co/Kzi4qhJ6Vm @ayane_incさんから
          #AYANE_online
          """
        "truncated" => false
        "entities" => array:4 [
          "hashtags" => array:1 [
            0 => array:2 [
              "text" => "AYANE_online"
              "indices" => array:2 [
                0 => 65
                1 => 78
              ]
            ]
          ]
          "symbols" => []
          "user_mentions" => array:1 [
            0 => array:5 [
              "screen_name" => "ayane_inc"
              "name" => "彩音インターナショナル株式会社"
              "id" => 1234567890
              "id_str" => "1234567890"
              "indices" => array:2 [
                0 => 50
                1 => 60
              ]
            ]
          ]
          "urls" => array:1 [
            0 => array:4 [
              "url" => "https://t.co/Kzi4qhJ6Vm"
              "expanded_url" => "https://ayane.co.jp/product/coin-case_wakiwakiparty"
              "display_url" => "ayane.co.jp/product/coin-c…"
              "indices" => array:2 [
                0 => 26
                1 => 49
              ]
            ]
          ]
        ]
        "source" => "<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>"
        "in_reply_to_status_id" => null
        "in_reply_to_status_id_str" => null
        "in_reply_to_user_id" => null
        "in_reply_to_user_id_str" => null
        "in_reply_to_screen_name" => null
        "geo" => null
        "coordinates" => null
        "place" => null
        "contributors" => null
        "is_quote_status" => false
        "retweet_count" => 2
        "favorite_count" => 7
        "favorited" => true
        "retweeted" => true
        "possibly_sensitive" => false
        "lang" => "ja"
      ]
      "is_quote_status" => false
      "retweet_count" => 2
      "favorite_count" => 0
      "favorited" => true
      "retweeted" => true
      "possibly_sensitive" => false
      "lang" => "ja"
    ]
    "contributors_enabled" => false
    "is_translator" => false
    "is_translation_enabled" => false
    "profile_background_color" => "C0DEED"
    "profile_background_tile" => false
    "profile_link_color" => "1DA1F2"
    "profile_sidebar_border_color" => "C0DEED"
    "profile_sidebar_fill_color" => "DDEEF6"
    "profile_text_color" => "333333"
    "profile_use_background_image" => true
    "has_extended_profile" => true
    "default_profile" => true
    "default_profile_image" => false
    "following" => false
    "follow_request_sent" => false
    "notifications" => false
    "translator_type" => "none"
    "suspended" => false
    "needs_phone_verification" => false
    "url" => "https://t.co/UNrUdL5qX3"
    "profile_background_image_url" => "http://abs.twimg.com/images/themes/theme1/bg.png"
    "profile_background_image_url_https" => "https://abs.twimg.com/images/themes/theme1/bg.png"
    "profile_image_url" => "http://pbs.twimg.com/profile_images/1205169805948411905/E_tsyv7t_normal.jpg"
    "profile_image_url_https" => "https://pbs.twimg.com/profile_images/1205169805948411905/E_tsyv7t_normal.jpg"
    "profile_banner_url" => "https://pbs.twimg.com/profile_banners/1732746061/1576170124"
    "location" => ""
    "description" => """
      AYANE は イラストレーションとシステム両面からエンターテインメントを提案します。日本のエンターテインメントを世界へ発信することに取り組み続けます。
      代表的なプロジェクト スーパーねねにゃん @nenenyan_com / 桜Exhibition @hyacca_info
      """
  ]
  +"avatar_original": "http://pbs.twimg.com/profile_images/1205169805948411905/E_tsyv7t.jpg"

Twitterはかなりな情報が取得できるようですね。
申請が難しいだけあって、なかなかおもしろいことができそうな感じです。
やりがいがありそうですね!

以上、何かのお役に立てたら幸いです。

次回は、画面系をやってみたいと思っています。

参考

以下の記事を参考にさせていただきました。
ありがとうございます。

https://qiita.com/u-dai/items/91df3b923dc82fed5b76
https://qiita.com/KeisukeKudo/items/18dd8a342a4bdd43913c
https://qiita.com/zaburo/items/26e94bce0068f479a8e8

11
11
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?