Nuxt.js + Auth0 + Spring Boot で作る認証付きSPA 【 vol.4 Spring と auth0組み込み編 】


# ここまでのおさらい
前回 [Nuxt.js + Auth0 + Spring Boot で作る認証付きSPA 【 vol.3 Nuxtとauth0組み込み編 】](https://qiita.com/mijinco0612/items/3adc49357ef619fd5c3) で
Nuxtとauth0を利用してgoogleでユーザ認証することができました。
今回はSpringとauth0を利用してサーバサイドを作成していきます。

## 今回やることのイメージ
![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/82787/eb536034-f4f0-aad5-bb4f-90000c75a152.png)

## Spring boot　プロジェクトのテンプレートを作る
[SPRING INITIALIZR](https://start.spring.io/)でプロジェクトのテンプレートを作成します。
今回は　DependenciesにRestRepositoriesのみ追加しました。

![スクリーンショット 2018-07-05 17.30.32.png](https://qiita-image-store.s3.amazonaws.com/0/82787/2560df4b-6d6d-9721-1965-ad00d75867cb.png)

## [pom.xmlに以下のDependenciesの追加する](https://github.com/mijinco0612-self-improvement/spring-auth0/commit/d755a9a18029b60f8d75f247b15c0d2b444adb64)
```xml:pom.xml
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>auth0</artifactId>
			<version>1.0.0</version>
		</dependency>

		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>auth0-spring-security-api</artifactId>
			<version>1.0.0-rc.3</version>
		</dependency>
```
## [aplication.ymlを追加する](https://github.com/mijinco0612-self-improvement/spring-auth0/commit/2333d61841d6da90aaf1336b4c57a20a39845ac0)
aplicaiton.propertiesからapplicaiton.ymlに置換し

起動ポートを28080に変更します。[^1]

auth0-spring-security-apiを使用する際にauth0の`audience`と`issuer`の接続情報が必要になります。
ymlにハードコードするのは避けたかったので環境変数から参照するようにします。

[前回、環境変数を登録した](https://qiita.com/mijinco0612/items/3adc49357ef619fd5c3c#auth0domain%E3%81%A8auth0clientid%E3%81%A8%E3%81%84%E3%81%86%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B)ときと同じように環境変数を追加します。

```bash:bashrcに登録する場合
vi ~/.bashrc
# 以下を.bashrcに追加
export auth0issuer=https://**************/ #****には前回登録したauth0Domainと同じ値が入ります

#: wqで保存後、以下を実行するかターミナルを再起動させる。
source ~/.bashrc
```
*audienceは前回登録したauth0ClientIDと同じ値を使用するので追加は割愛しました。

```yaml:application.yml
server:
  port: 28080
auth0:
  audience : ${auth0ClientID}
  issuer : ${auth0issuer}
```

##　[controllerの設置](https://github.com/mijinco0612-self-improvement/spring-auth0/blob/feature/add-auth0-settings/src/main/java/com/mijinco0612/springauth0/controller/api/v1/DemoController.java)
public/privateという文字列を返すだけのシンプルなEndPointを設置します。

```java:DemoController
package com.mijinco0612.springauth0.controller.api.v1;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @ResponseBody
    @GetMapping(value = "/api/v1/public")
    public String publicApi() {
        return "public";
    }

    @ResponseBody
    @GetMapping("/api/v1/private")
    public String privateApi() {
        return "private";
    }
}
```
最終的には
`/api/v1/public`へのリクエストは認証なしで許可
`/api/v1/private`へのリクエストは認証済の場合許可するように制御します。
現時点では保護されていないためどちらもリクエストが通ります。


##WebSecurityConfigを追加
さあ、apiを保護していきましょう。といっても以下を追加するだけです。

```java:WebSecurityConfig
package com.mijinco0612.springauth0.security;

import com.auth0.spring.security.api.JwtWebSecurityConfigurer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Value("${auth0.audience}") 
    private String audience;  //ymlに設定したaudienceを代入

    @Value("${auth0.issuer}")
    private String issuer; //ymlに設定したissuerを代入

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/api/v1/public").permitAll()　// publicは制限なし
                .antMatchers("/**").authenticated(); // それ以外は認証済みの場合のみ許可

        JwtWebSecurityConfigurer
                .forRS256(audience, issuer)　 //Request Headers Authorization tokenを検証
                .configure(http);
    }
}
```

## 動作確認してみる
ここまでで、サーバサイドの準備は完了です。実際にリクエストを行って挙動を確認してみましょう。
Postmanについては[こちら](https://www.webprofessional.jp/master-api-workflow-postman/)とか[こちら](https://qiita.com/tags/postman)を参照してみてください。
今回は[Postman for Mac](https://www.getpostman.com/apps)を使用しました。

###アプリケーションを起動させます。

```bash:Terminal
~/s/spring-auth0 ❯❯❯ cd ~/study-auth0/spring-auth0/  #作成したプロジェクトのルートディレクトリへ移動
mvn clean spring-boot:run  
[INFO] Scanning for projects...
[INFO] 
[INFO] --------------------< com.mijinco0612:spring-auth0 >--------------------
[INFO] Building spring-auth0 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
~~~~~~~~~~~~中略~~~~~~~~~~~~
2018-07-06 07:36:54.821  INFO 33804 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-07-06 07:36:55.054  INFO 33804 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 28080 (http) with context path ''
2018-07-06 07:36:55.068  INFO 33804 --- [           main] c.m.springauth0.SpringAuth0Application   : Started SpringAuth0Application in 15.998 seconds (JVM running for 24.986)
```
port:28080でアプリケーションが起動しました。

### Postmanを使ってリクエストをしてみる。

先ずは`http://localhost:28080/api/v1/public`にリクエストしてみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82787/dbfddaad-3d23-ef99-1656-a9afbc0fcb78.png)

response body に　`public`の文字列が返ってきてますね。成功です。

次に`http://localhost:28080/api/v1/private`にリクエストしてみます。
認証はまだしていませんので、401:Unauthorizedが返ってくるはずです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/82787/66080905-c7f8-d738-0c7b-f003b1b01715.png)

想定したとおりの挙動ですね。成功です！

では認証済みの場合の挙動を確認しましょう。
前回 [Nuxt.js + Auth0 + Spring Boot で作る認証付きSPA 【 vol.3 Nuxtとauth0組み込み編 】](https://qiita.com/mijinco0612/items/3adc49357ef619fd5c3)で作成したNuxtアプリケーションでログインを行いchrome developer toolでLocal StorageのidTokenの値をコピーしましょう。
![idTokenコピー.png](https://qiita-image-store.s3.amazonaws.com/0/82787/218266b2-1d3a-06ba-b155-ab3d14b0fd16.png)

コピーできたらPostmanのAuthorizationタブに遷移し、TYPEに***BearerToken***を選択して、コピーしてきたidTokenをToken フィールドにペーストします。
![token貼り付け.png](https://qiita-image-store.s3.amazonaws.com/0/82787/3be2b083-3e6c-b8ac-28ca-7054d0561b1f.png)

再度リクエストを試してみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/82787/b34063a1-9163-59e5-dfed-39c6e7c5900a.png)

今度は無事`private`という文字列が返ってきました。成功です！

[jwt.io](https://jwt.io/)などをつかって、先程のidTokenを書き換えてリクエストしてみると
401:Unauthorizedが返ってくることが確認できます。
Tokenの検証が行われていることをお手元でも実際に確認してみてください。


## まとめ

非常にシンプルですが、これでサーバサイドは完了です。
実際にJwtの検証をjjwtなどを利用して作成されたことのある方は手順の少なさに驚かれたのではと思います。
次回はいよいよNuxtとSpringをつないでアプリケーションを完成させます。

## 参考
- [Securing Spring Boot with JWTs](https://auth0.com/blog/securing-spring-boot-with-jwts/)



##脚注
[^1]: デフォルトの８０８０ポートを使用したい場合、この設定は不要です。