質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

コールバック

コールバックは他のコードに引数として渡されるコードのことを指します。

Amazon EC2

Amazon EC2は“Amazon Elastic Compute Cloud”の略称です。Amazon Web Services(AWS)の一部であり、仮想化されたWebサーバーのコンピュータリソースをレンタルできるサービスです。

Q&A

解決済

1回答

1728閲覧

【EC2】LaravelでTwitter認証をするとコールバックで『404 Not Found』が返される(開発環境ではエラーが出ない)

NULL_000000

総合スコア3

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

コールバック

コールバックは他のコードに引数として渡されるコードのことを指します。

Amazon EC2

Amazon EC2は“Amazon Elastic Compute Cloud”の略称です。Amazon Web Services(AWS)の一部であり、仮想化されたWebサーバーのコンピュータリソースをレンタルできるサービスです。

0グッド

0クリップ

投稿2021/12/17 21:23

前提・実現したいこと

EC2にデプロイしたLaravelアプリケーションに、Twitterアカウントを使ったログイン認証機能の実装に挑戦しています。
dockerを活用した開発環境(LEMP環境)では正常にTwitter認証が機能していますが、 EC2にデプロイしてTwitter認証の動作確認をすると、コールバック時に開発環境では出ない【404 Not Found】が返ります。

発生している問題・エラーメッセージ

404 Not Found

該当のソースコード

.env(実際には入力されています)

TWITTER_CLIENT_ID="<ID>" TWITTER_CLIENT_SECRET="<SECRET>" TWITTER_CLIENT_ACCESS_TOKEN="<ACCESS_TOKEN>" TWITTER_CLIENT_ACCESS_TOKEN_SECRET="<ACCESS_TOKEN_SECRET>"

app/Http/Controllers/Auth/LoginController.php

PHP

1<?php 2 3namespace App\Http\Controllers\Auth; 4 5use App\Http\Controllers\Controller; 6use App\User; 7use App\Providers\RouteServiceProvider; 8use Illuminate\Foundation\Auth\AuthenticatesUsers; 9use Illuminate\Http\Request; 10use Laravel\Socialite\Facades\Socialite; 11 12class LoginController extends Controller 13{ 14 public function __construct() 15 { 16 $this->middleware('guest')->except('logout'); 17 } 18 19 public function redirectToProvider(string $provider) 20 { 21 return Socialite::driver($provider)->redirect(); 22 } 23 24 public function handleProviderCallback(Request $request, string $provider) 25 { 26 $providerUser = Socialite::driver($provider)->user(); 27 28 if($provider === 'google') { 29 $user = User::where('email', $providerUser->getEmail())->first(); 30 } elseif($provider === 'twitter') { 31 $user = User::where('twitter_id', $providerUser->getId())->first(); 32 } 33 34 if ($user) { 35 $this->guard()->login($user, true); 36 return $this->sendLoginResponse($request); 37 } 38 39 if($provider === 'google') { 40 return redirect()->route('register.{provider}', [ 41 'provider' => $provider, 42 'email' => $providerUser->getEmail(), 43 'token' => $providerUser->token, 44 ]); 45 } elseif($provider === 'twitter') { 46 return redirect()->route('register.{provider}', [ 47 'provider' => $provider, 48 'twitter_id' => $providerUser->getId(), 49 'token' => $providerUser->token, 50 'tokenSecret' => $providerUser->tokenSecret, 51 ]); 52 } 53 54 } 55} 56

app/Http/Controllers/Auth/RegisterController.php

<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use App\User; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Laravel\Socialite\Facades\Socialite; class RegisterController extends Controller { use RegistersUsers; protected $redirectTo = RouteServiceProvider::HOME;         public function __construct() { $this->middleware('guest'); }     protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'alpha_num', 'min:3', 'max:16', 'unique:users'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } public function showProviderUserRegistrationForm(Request $request, string $provider) { $token = $request->token; $providerUser = Socialite::driver($provider); //google if ($provider === 'google') { $providerUser = $providerUser->userFromToken($token); return view('auth.social_register', [ 'provider' => $provider, 'email' => $providerUser->getEmail(), 'token' => $providerUser->token, ]); //twitter } elseif ($provider === 'twitter') { $tokenSecret = $request->tokenSecret; $providerUser = $providerUser->userFromTokenAndSecret($token, $tokenSecret); return view('auth.social_register', [ 'provider' => $provider, 'twitter_id' => $providerUser->getId(), 'token' => $providerUser->token, 'tokenSecret' => $providerUser->tokenSecret, ]); } } public function registerProviderUser(Request $request, string $provider) { //google if($provider === 'google') { $request->validate([ 'name' => ['required', 'string', 'min:3', 'max:15', 'unique:users'], 'age' => ['numeric', 'min:1', 'max:100', 'nullable'], 'token' => ['required', 'string'], ]); //twitter } elseif($provider === 'twitter') { $request->validate([ 'name' => ['required', 'string', 'min:3', 'max:15', 'unique:users'], 'age' => ['numeric', 'min:1', 'max:100', 'nullable'], 'token' => ['required', 'string'], 'tokenSecret' => ['required', 'string'], ]); } $token = $request->token; $providerUser = Socialite::driver($provider); //google if ($provider === 'google') { $providerUser = $providerUser->userFromToken($token); //twitter } elseif ($provider === 'twitter') { $tokenSecret = $request->tokenSecret; $providerUser = $providerUser->userFromTokenAndSecret($token, $tokenSecret); } //google if ($provider === 'google') { $user = User::create([ 'name' => $request->name, 'email' => $providerUser->getEmail(), 'password' => null, ]); //twitter } elseif ($provider === 'twitter') { $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'twitter_id' => $providerUser->getId(), 'password' => null, ]); } $this->guard()->login($user, true); return $this->registered($request, $user) ?: redirect($this->redirectPath()); } }

config/services.php

PHP

1<?php 2 3return [ 4 5 /* 6 |-------------------------------------------------------------------------- 7 | Third Party Services 8 |-------------------------------------------------------------------------- 9 | 10 | This file is for storing the credentials for third party services such 11 | as Mailgun, Postmark, AWS and more. This file provides the de facto 12 | location for this type of information, allowing packages to have 13 | a conventional file to locate the various service credentials. 14 | 15 */ 16 17 'mailgun' => [ 18 'domain' => env('MAILGUN_DOMAIN'), 19 'secret' => env('MAILGUN_SECRET'), 20 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 ], 22 23 'postmark' => [ 24 'token' => env('POSTMARK_TOKEN'), 25 ], 26 27 'ses' => [ 28 'key' => env('AWS_ACCESS_KEY_ID'), 29 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 ], 32 33 'google' => [ 34 'client_id' => env('GOOGLE_CLIENT_ID'), 35 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 36 'redirect' => env('APP_URL') . '/login/google/callback', 37 ], 38 39 'twitter' => [ 40 'client_id' => env('TWITTER_CLIENT_ID'), 41 'client_secret' => env('TWITTER_CLIENT_SECRET'), 42 'redirect' => env('APP_URL') . '/login/twitter/callback', 43 ], 44 45];

routes/web.php

<?php Auth::routes(); Route::prefix('login')->name('login.')->group(function () { Route::get('/{provider}', 'Auth\LoginController@redirectToProvider')->name('{provider}'); Route::get('/{provider}/callback', 'Auth\LoginController@handleProviderCallback')->name('{provider}.callback'); }); Route::prefix('register')->name('register.')->group(function () { Route::get('/{provider}', 'Auth\RegisterController@showProviderUserRegistrationForm')->name('{provider}'); Route::post('/{provider}', 'Auth\RegisterController@registerProviderUser')->name('{provider}'); }); if (app()->environment('production')) { URL::forceScheme('https'); }

試したこと

Callback URL/Redirect URLの整合性チェック
イメージ説明

補足情報(FW/ツールのバージョンなど)

OAuth 2.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/12/18 03:01

.envのAPP_URLはhttpsで指定していますか?
NULL_000000

2021/12/18 04:37

はい。httpsで指定しております。 Google認証を既に実装していまして、こちらは開発環境、本番環境ともに正常に動作しています。 開発環境でTwitter認証を実装、正常に動作することを確認した後にデプロイしました。 ソースの変更は本番環境に反映されておりTwitterアカウントの認証画面までは遷移できますが、現状ではコールバックがうまく動作していない状態です。
guest

回答1

0

自己解決

自己解決しました。

結論、本番環境で[php artisan migrate]コマンドを実行していないことが原因でした。
開発環境でTwitter認証を実装するにあたり、DBのテーブル構成を変更して[php artisan migrate]コマンドを実行した場面がありました。

無事、開発環境で正常に動作したためGitHubにプッシュ、Circle CIとCodeDeployを活用してデプロイを実行しましたが、この過程で[php artisan migrate]コマンドの実行が抜けていました。
API連携にばかり注目してしまい、ローカルと本番環境のテーブル構成の差異に気付くのが遅くなってしまいました。

本番環境で[php artisan migrate]コマンドを実行すると、Twitter認証を実装することができました。
お騒がせしました。

投稿2021/12/18 06:23

NULL_000000

総合スコア3

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問