LaravelでInstagramでログインをやってみた

# 【重要】 2021-02-09 追記
Instagram Legacy APIの仕様変更により、以下の方法は使えなくなったそうです。
それに伴って後日、本記事は非公開といたします。
https://did2memo.net/2020/07/17/instagram-login-error-oauthexception/
@SE_O_T さん、教えてくださってありがとうございました！

# 以下、削除予定
LaravelでInstagramログインをしてみた。

利用にはInstagramAppを作成する必要があるのだが、そこはまた別の記事にやるとして、今回はある前提で話を進めていきます。
※ちなみにInstagramAppの作成はこちらから行えます。
→ https://www.instagram.com/developer/

# 環境
- PHP 5.6
- Laravel 5.2

# 使用ライブラリ
- Instagram PHP API
    - https://github.com/cosenary/Instagram-PHP-API

# ライブラリインストール

```php:install.cmd
composer require cosenary/instagram
```
# 設定
Appの情報は定数に保存しておいてもいいのだが、本番でAppが変わった際などに修正がしやすいように、.envを用いたい。
/config/以外の部分に.envを用いてしまうと、cache周りの操作がめんどくさいので、設定ファイルを作成する。

```php:config/instagram.php
<?php
return [
    'client_id' => env('INSTAGRAM_KEY'),
    'client_secret' => env('INSTAGRAM_SECRET'),
    'callback_url' => env('INSTAGRAM_REDIRECT_URI'),
];
```
```php:.env
INSTAGRAM_KEY=`自分のAppのClient ID`
INSTAGRAM_SECRET=`自分のAppのClient Secret`
INSTAGRAM_REDIRECT_URI=`自分のHOST`/instagram/callback/
```

# ソースコード
まずは画面上にInstagramでログインボタンを配置する。

その際、URLはInstagramAPIのものにするが、個人的にAppのIDやSecretKeyが見えるところにあるのは気持ちが悪いので、aタグに生で入れないようにする。
※もちろんviewに直接指定しても可能です。

## ルーティング
```php:app/Http/routes.php
# Instagram login
Route::get('/instagram/', 'InstagramController@instagramLogin');

# Instagram callback
Route::get('/instagram/callback/', 'InstagramController@instagramCallback');
```

## View
```php:resource/view/login.blade.php
<a href="{{url('/instagram/')}}">
    Instagramでログイン・登録
</a>
```

## Controller
まずはartisanでファイルを作成。

```php:makeController.cmd
php artisan make:controller InstagramController
```

ゴリゴリ書いていく。

```php:app/Http/Controller/InstagramController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;

use MetzWeb\Instagram\Instagram;

/**
 * Instagramでログインを行う際のController
 */
class InstagramController extends Controller
{
    # 共通で使うので、constructに格納
    private $instagram;

    function __construct() {
        # configからAppの値を取得し、インスタンス化
        $this->instagram = new Instagram(array(
            'apiKey' => config('instagram.client_id'),
            'apiSecret' => config('instagram.client_secret'),
            'apiCallback' => config('instagram.callback_url')
        ));
    }

    /**
     * Instagramで登録、ログインを押された際の処理
     */
    public function instagramLogin() {
        return redirect($this->instagram->getLoginUrl(array(
            # アクセスする権限をここで指定可能
            # ただし、対応していない権限も存在しているので、その場合はURLを生で書くようにする
            'basic'
        )));
    }

    /**
     * Instagramで登録、ログインを押された後にリダイレクトされた際の処理
     * Instagramの情報を取得できる
     */
    public function instagramCallback(Request $request) {
        # URLにcodeが入っているので取得
        $code = $request->code;

        # 取得したcodeを利用し、OAhtu認証
        $data = $this->instagram->getOAuthToken($code);
        $this->instagram->setAccessToken($data);

        # OAuth認証が完了したので、$instagram->"method"で好きなAPIが叩けるようになっている
        # 今回はInstagramでログイン機能なので、getUser()を使用
        $user_data = $this->instagram->getUser();

        echo '<pre>';
        var_dump($user_data);
        echo '</pre>';
    }
}
```

これで以下のような結果が返ってくるので、取得したユーザー情報をDBに格納し、Laravelの[Auth::Login($user)](https://readouble.com/laravel/5.2/ja/authentication.html)を使ってしまえば、認証完了となる。
※この際、ユニーク値は下記データ中の"id"で行った。

```json:user.json
object(stdClass)#154 (2) {
  ["data"]=>
  object(stdClass)#155 (7) {
    ["id"]=>
    string(9) "223689238"
    ["username"]=>
    string(15) "daiki.sekiguchi"
    ["profile_picture"]=>
    string(105) "https://scontent.cdninstagram.com/t51.2885-19/s150x150/16789727_236142133514690_5385687353354354688_a.jpg"
    ["full_name"]=>
    string(15) "Daiki Sekiguchi"
    ["bio"]=>
    string(0) ""
    ["website"]=>
    string(0) ""
    ["counts"]=>
    object(stdClass)#156 (3) {
      ["media"]=>
      int(2)
      ["follows"]=>
      int(60)
      ["followed_by"]=>
      int(56)
    }
  }
  ["meta"]=>
  object(stdClass)#157 (1) {
    ["code"]=>
    int(200)
  }
}
```

# 所感
思ったより簡単にできるなぁというのが感想です。

ただ、実際、僕がやったときはライブラリの対応していない権限を利用したかったため、instagramLogin()内のredirectURLを生で書いてしまいました。
生で書いてあると、なんかダサくて気に食わなかったです。

InstagramAppの作成方法についてはどこかで記述しようかなぁと思います。

# 参考URL
- Instagram API Doc
    - https://www.instagram.com/developer/authentication/
- Instagram PHP API V2
    - https://github.com/cosenary/Instagram-PHP-API

# 合わせてどうぞ！
OAuth認証後、ユーザーの投稿メディアを全取得してみましたので、良かったら合わせてご覧ください。

- LaravelでInstagramに投稿された写真を全取得してみた
    - [http://qiita.com/daiki_44/items/9a1f3f78a76dd3dc8e1f](http://qiita.com/daiki_44/items/9a1f3f78a76dd3dc8e1f?laravel_login)