認証が必要なLaravelAPIをAngularから呼ぶときに便利だったもの紹介

# はじめに

こんにちは。
今回はLaravelでAPIサーバを立てて、Angularから呼ぶときに役立った記事やライブラリ、ツールを紹介します。

紹介するのは、次の3つ。

- Cors
    - 同一生成元ポリシーで弾かれないリソース共有をする仕組み
- JWT
    - 認証に使うJsonWebToken
- PhpStorm TestRestful web service
    - ストレスフリーなAPIの検証

## CorsをLaravelに導入
参考1,2を元に、Corsを導入した。
LaravelのglobalMiddlewareに設定することで、全てのリクエストに対して実行する。

middlewareを作る。

```
$ php artisan make:middleware Cors
```

->header('Access-Control-Allow-Origin', '*')
のアスタリスクにAPIへのアクセス許可するドメインを追記する。

```Cors.php
    public function handle($request, Closure $next)
    {
        if ($request->isMethod('options')) {
            return response('', 200)
              ->header('Access-Control-Allow-Origin', '*')
              ->header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE')
              ->header('Access-Control-Allow-Headers', 'accept, content-type, 
                x-xsrf-token, x-csrf-token');
        }
        return $next($request);
    }
```

globalMiddlewareにCorsを追記する。

```app/Http/Kernel.php
protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \App\Http\Middleware\Cors::class,
    ];
```



## JWTを導入
JWTの利便性は、誰がリクエストしたのかを安全で簡単にやりとり出来るところにある。
JWTをデコードすると誰がリクエストしたかがわかり、そのJWTが秘密鍵でデコードできるということは
認証は既に完了した人だということなので、再度認証する必要もない。

LaravelとAngular共に便利なライブラリが用意されているので、それらを利用する。

Laravel側では、認証情報がPOSTされたときにJWTを生成して返す仕組みを導入。
Angular側では、JWTを持っている場合はHTTPリクエストにTokenを付与する仕組みを導入。



### Laravelでやること
Laravel側では下記のライブラリを使用した。
https://github.com/tymondesigns/jwt-auth
導入手順はwikiに詳しく書いてあるので、ここでは書かない。
実際にjwt-authを利用している部分だけ書く。

まずは、routes/api.phpにルーティングを追記。
getでloginしているユーザ情報を取得。
postでlogin情報を渡し、Tokenを得る。

```routes/api.php
// http://exsample.com/api/authenticate
Route::get('/authenticate', 'AuthenticateController@index');
Route::post('/authenticate', 'AuthenticateController@auth');
```

https://github.com/tymondesigns/jwt-auth/wiki
の通りにaliases等の設定が必要。
ここでは、emailとpasswordを使って認証を行いtokenを返す。

```app/Http/Controllers/AuthenticateController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class AuthenticateController extends Controller
{

    /**
     * constructor
     */
    public function __construct(){
        $this->middleware('jwt.auth', ['except' => ['showSignIn', 'auth']]);
    }


    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $loginUser = JWTAuth::parseToken()->toUser();
        return response()->json(['user' => $loginUser]);
    }

    /**
     * Authenticate from email and password
     */
    public static function auth(Request $request){
        $credentials = $request->only('email', 'password');
        try {
            // verify the credentials and create a token for the user
            if (! $token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'invalid credentials'], 401);
            }
        } catch (JWTException $e) {
            // something went wrong
            return response()->json(['error' => 'could not create token'], 500);
        }

        return response()->json(compact('token'));
    }
}
```

### Angularでやること
Angualar側では下記のライブラリを使用した。
https://github.com/auth0/angular-jwt
auth0/angular-jwtでは、HttpリクエストにJWTを付加するラッパーを用意している。
認証が成功したときにlocalStorageにkey:id_tokenでJWTを保存しておく。
認証が必要なリクエストを送るときには、localStorageからid_tokenを呼んでリクエストに付加する。


認証が必要なリクエスト時は、authHttpでリクエストを行うことで自動的にtokenが付与されるので、認証関連の処理を意識する必要がない。
localStorage以外に保持したい場合は、optionからtokenGetterの方法を指定できる。


## PhpStormのTestRestfulWebServiceが便利
ソース改修後にブラウザと行き来するストレスから解放される。

phpStorm→Tools→TestRestfulWebService
で開く。
Laravelで作ってみたAPIを検証してみる。

Host/port, Path, HttpMethodを設定してRequestParameterを設定。
作った認証APIに認証情報をPostで渡してみる。
<img width="1243" alt="スクリーンショット 2016-12-18 18.34.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/101531/867e1194-163e-c94a-ba00-294d1bba020c.png">

Responseタブが開き、JWTが帰ってくる。
<img width="1241" alt="スクリーンショット 2016-12-18 18.33.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/101531/749b5474-6137-5e8c-8c66-e104e8a7e45c.png">

帰ってきたJWTを設定して認証できてるか試す。
<img width="1242" alt="スクリーンショット 2016-12-18 18.39.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/101531/888afee5-6ddb-cda1-44ac-ee0550bd1493.png">

秘密鍵を使って複合した結果が帰ってきた。
![スクリーンショット 2016-12-18 18.40.55.jpg](https://qiita-image-store.s3.amazonaws.com/0/101531/24e2fb86-eb9d-29ab-55ba-bd775d35735e.jpeg)

## まとめ
世の中便利なツールやライブラリが色々ありますね。
最速で開発するために、こういうものをどんどん使いこなしていきたい。


## 参考
参考1:https://blog.nikhilben.com/2015/09/02/laravel5-rest-api-and-cors/
参考2:http://qiita.com/fluke8259/items/c884bada22ccd286cf48
参考3:https://jwt.io/introduction/