Auth0のRBAC SettingsとJWTの内容について


# はじめに
Auth0を使ってJWT認証をしようとしてたがRBACやPermissionの設定等がいまいちわからなかったため検証した。

# 前提
フロントエンド : Vue 3.0
バックエンド : Java 11
認証サービス : [Auth0](https://auth0.com/jp)

バックエンド側はJWTのスコープを見てアクセス制御している。
OKな権限だったらHTTP Status:200, NGな権限だったらHTTP Status:403を返却する

``` java
@Override
	public void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
				.mvcMatchers("/api/private-scoped-read").hasAuthority("SCOPE_read:message")
				.mvcMatchers("/api/private-scoped-write").hasAuthority("SCOPE_write:message")
				.and().cors()
				.and().oauth2ResourceServer().jwt();
	}
```
Springの他の実装は[Spring Boot API: Authorization](https://auth0.com/docs/quickstart/backend/java-spring-security5/01-authorization)を参照してください

# まとめ
## Auth0のユーザー権限設定とユーザーの同意の組み合わせ表
### RABC : ON
* Add Permissions in the Access TokenがOFFの場合はJWTにPermissionの項目はない
<table>
<thead>
<tr>
<th style="text-align:left" colspan="1"></th>
<th style="text-align:left" colspan="2">Auth0</th>
<th style="text-align:left">フロント</th>
<th style="text-align:left"></th>
<th style="text-align:left">認証画面</th>
<th style="text-align:left" colspan="2">API呼び出し結果 HTTP Status</th>
<th style="text-align:left" colspan="2">JWT</th>
</tr>
<tr>
<th style="text-align:left"></th>
<th style="text-align:left">API Permission</th>
<th style="text-align:left">User Permission</th>
<th style="text-align:left">Scope</th>
<th style="text-align:left"></th>
<th style="text-align:left">ユーザーに同意を求める権限</th>
<th style="text-align:left">Read</th>
<th style="text-align:left">Write</th>
<th style="text-align:left">Scope</th>
<th style="text-align:left">Permission</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">①</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">-</td>
<td style="text-align:left">read:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email</td>
<td style="text-align:left">403</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email</td>
<td style="text-align:left">-</td>
</tr>
<tr>
<td style="text-align:left">②</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">-</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email</td>
<td style="text-align:left">403</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email</td>
<td style="text-align:left">read:message</td>
</tr>
<tr>
<td style="text-align:left">③</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">read:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email<br>read:message</td>
<td style="text-align:left">200</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email<br>read:message</td>
<td style="text-align:left">read:message</td>
</tr>
<tr>
<td style="text-align:left">④</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">write:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email</td>
<td style="text-align:left">403</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email</td>
<td style="text-align:left">read:message</td>
</tr>
<tr>
<td style="text-align:left">⑤</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">read:message<br>write:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email<br>read:message</td>
<td style="text-align:left">200</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email<br>read:message</td>
<td style="text-align:left">read:message</td>
</tr>
</tbody>
</table>

* JWTのScopeに設定される値は、Auth0のUserに設定されているかつ同意した権限
* JWTのPermissionに設定される値は、Auth0のUserに設定されている権限
   * 同意していない権限もPermissionに設定される

### RABC : OFFの場合
* Add Permissions in the Access TokenはONにできない
<table>
<thead>
<tr>
<th style="text-align:left" colspan="1"></th>
<th style="text-align:left" colspan="2">Auth0</th>
<th style="text-align:left">フロント</th>
<th style="text-align:left"></th>
<th style="text-align:left">認証画面</th>
<th style="text-align:left" colspan="2">API呼び出し結果 HTTP Status</th>
<th style="text-align:left" colspan="2">JWT</th>
</tr>
<tr>
<th style="text-align:left"></th>
<th style="text-align:left">API Permission</th>
<th style="text-align:left">User Permission</th>
<th style="text-align:left">Scope</th>
<th style="text-align:left"></th>
<th style="text-align:left">ユーザーに同意を求める権限</th>
<th style="text-align:left">Read</th>
<th style="text-align:left">Write</th>
<th style="text-align:left">Scope</th>
<th style="text-align:left">Permission</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">①</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">-</td>
<td style="text-align:left">read:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email<br>read:message</td>
<td style="text-align:left">200</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email<br>read:message</td>
<td style="text-align:left">-</td>
</tr>
<tr>
<td style="text-align:left">②</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">-</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email</td>
<td style="text-align:left">403</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email</td>
<td style="text-align:left">-</td>
</tr>
<tr>
<td style="text-align:left">③</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">read:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email<br>read:message</td>
<td style="text-align:left">200</td>
<td style="text-align:left">403</td>
<td style="text-align:left">openid profile email<br>read:message</td>
<td style="text-align:left">-</td>
</tr>
<tr>
<td style="text-align:left">④</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">write:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email<br>write:message</td>
<td style="text-align:left">403</td>
<td style="text-align:left">200</td>
<td style="text-align:left">openid profile email <br>write:message</td>
<td style="text-align:left">-</td>
</tr>
<tr>
<td style="text-align:left">⑤</td>
<td style="text-align:left">read:message<br>write:message </td>
<td style="text-align:left">read:message</td>
<td style="text-align:left">read:hoge<br>write:message</td>
<td style="text-align:left"></td>
<td style="text-align:left">profile<br>email<br>read:message</td>
<td style="text-align:left">200</td>
<td style="text-align:left">200</td>
<td style="text-align:left">openid profile email<br>read:message<br>write:message</td>
<td style="text-align:left"></td>
</tr>
</tbody>
</table>

* JWTのスコープに設定されるのは同意した権限
  * ユーザーに権限がついてなくてもAPIにアクセスできる 

### JWTのSCOPEに設定される組み合わせ
|RBAC|項目|
|-|-|
|ON|User Permission<br>同意した権限(フロントのscopeで設定した値)|
|OFF|同意した権限(フロントのscopeで設定した値)|


# 詳細
## Auth0の設定
### API Permission
このAPIが要求するPermissionを設定する
フロント側でここにない権限をscopeに設定しても認証画面に反映されない
![API Details - Google Chrome 2022_08_08 1_49_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236151/94c740fe-e19e-cc18-7eb4-4f2ab113feed.png)

### UserのPermission
APIに紐づいてる権限を付与できる。
Role毎の権限も個人毎の権限も設定可能

![User Details - Google Chrome 2022_08_10 3_31_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236151/3f9804d2-ed12-cc8c-bd46-9b54c0621fd8.png)

### RBAC
ここでRBACとトークンのON/OFFを設定
トークンをONにするとJWTにpermissionが追加される
![API Details - Google Chrome 2022_08_08 1_39_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236151/8e11aa11-114b-cd0d-1d7d-a38602523d96.png)

## フロント側の設定
``` vue.js
export const Auth0Plugin = createAuth0({
    domain: domain,
    client_id: clientId,
    redirect_uri: window.location.origin,
    audience: audience,
    scope: "read:message" 
});
```

scopeにユーザーに許可をもらいたい権限を記載する。複数ある場合はスペース区切り。
フロント側のscopeにread:messageを指定しているので、認証画面にメッセージのread権限を求める項目が表示される

![③login.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236151/4a02dec3-9757-3dfa-5cf8-ce3299d7de4c.jpeg)


Vueの他の実装は[Vue: Login](https://auth0.com/docs/quickstart/spa/vuejs/01-login)と、[The Complete Guide to Vue.js User Authentication with Auth0](https://auth0.com/blog/complete-guide-to-vue-user-authentication/)を参照してください