Spring + OAuth 2.0 + OpenID Connect

# **1. クイックスタート**

### **1.1. 認可サーバーをポート 8080 で起動**

```shell-session
$ git clone https://github.com/authlete/spring-oauth-server
$ cd spring-oauth-server
$ vi authlete.properties
$ mvn spring-boot:run
```


### **1.2. リソースサーバーをポート 8081 で起動**

```shell-session
$ git clone https://github.com/authlete/spring-resource-server
$ cd spring-resource-server
$ vi authlete.properties
$ mvn spring-boot:run
```


### **1.3. アクセストークンと ID トークンを発行**

```
http://localhost:8080/api/authorization
    ?client_id={クライアントID}
    &response_type=token+id_token
    &scope=openid
    &redirect_uri={リダイレクトURI}
    &state={任意文字列}
    &nonce={任意文字列}
```

Web ブラウザで上記 URL にアクセスし、表示された認可ページで、ログイン ID = `john`、 パスワード = `john` を入力し『Authorize』ボタンを押す。


### **1.4. 保護リソースエンドポイントのサンプルにアクセス**

```shell-session
$ curl http://localhost:8081/api/country/JP \
    -d access_token={アクセストークン}
```


### **1.5. ユーザー情報エンドポイント**（[OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html)）

```shell-session
$ curl http://localhost:8081/api/userinfo \
    -d access_token={アクセストークン}
```


### **1.6. ディスカバリーエンドポイント**（[OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)）

```shell-session
$ curl http://localhost:8080/.well-known/openid-configuration
```


### **1.7. JWK Set エンドポイント**（[RFC 7517](https://tools.ietf.org/html/rfc7517)）

```shell-session
$ curl http://localhost:8080/api/jwks
```


### **1.8. イントロスペクションエンドポイント**（[RFC 7662](https://tools.ietf.org/html/rfc7662)）

```shell-session
$ curl http://localhost:8080/api/introspection \
    -d token={アクセストークン}
```


### **1.9. アクセストークン削除**（リボケーションエンドポイント; [RFC 7009](https://tools.ietf.org/html/rfc7009)）

```
$ curl http://localhost:8080/api/revocation \
    -d token={アクセストークン}
```


# **2. アーキテクチャー**

**[spring-oauth-server](https://github.com/authlete/spring-oauth-server)** は OAuth 2.0 と OpenID Connect をサポートする認可サーバー兼 OpenID プロバイダーの実装です。

**[spring-resource-server](https://github.com/authlete/spring-resource-server)** は OpenID Connect で定義されているユーザー情報エンドポイントの実装を含むリソースサーバーの実装です。

どちらの実装も [Spring Boot](https://projects.spring.io/spring-boot/) を使用していますが、[Spring Security OAuth](http://projects.spring.io/spring-security-oauth/) は使っていません。かわりに、OAuth 2.0 と OpenID Connect の実装として [Authlete](https://www.authlete.com/) を使用しています。

**[Authlete](https://www.authlete.com/)** それ自身は認可サーバー・OpenID プロバイダーの実装ではなく、それらを実装するための Web API のセットです。

<img width="895" alt="relationship-between-frontend-server-and-authlete.png" src="https://qiita-image-store.s3.amazonaws.com/0/106044/40ca20ed-40b4-eae2-aaa5-1eb9647144ea.png">

このアーキテクチャーの一番の利点は、バックエンドサーバー（Authlete）が OAuth 2.0 と OpenID Connect の実装に集中でき、他の技術要素〜アイデンティティー管理、ユーザー認証、ログインセッション管理、API 管理、不正検出等〜を気にする必要がないことです。逆の言い方をすると、開発者は、OAuth 2.0 と OpenID Connect の実装を気にする必要なく、アイデンティティー管理やユーザー認証等で好きなソリューションを選択することができます。さらに言えば、開発者は、認可サーバー・OpenID プロバイダーを実装するのに、好きなプログラミング言語を選択することができます。このアーキテクチャーの詳細については、『[OAuth 2.0 / OIDC 実装の新アーキテクチャー](https://qiita.com/TakahikoKawasaki/items/b2a4fc39e0c1a1949aab)』を参照してください。

このアーキテクチャーのおかげで、フロントエンドサーバー（spring-oauth-server と spring-resource-server）は、アクセストークンやリフレッシュトークン、認可コード、クライアントアプリケーションのメタ情報、認可サーバー・OpenID プロバイダーのメタ情報などといった、OAuth 2.0 と OpenID Connect に関するデータを管理するためのデータベースを持つ必要がありません。これらのデータはバックエンドサーバー（Authlete）が管理します。

## **2.1. Spring Security OAuth に関する注意点**

Spring Security OAuth がデータベーステーブルのスキーマさえ提供していないことは、ここで述べておいたほうがよいかもしれません。次の文は、Spring Security OAuth の『[OAuth 2 Developers Guide](http://projects.spring.io/spring-security-oauth/docs/oauth2.html)』からの抜粋です。

> _NOTE: **the schema for the JDBC service is not packaged with the library** (because there are too many variations you might like to use in practice), but there is an example you can start from in the test code in github._

これはつまり、Spring Security OAuth ライブラリの API（`ClientDetails` インターフェース等）を調査し、対応するデータを保存するためのデータベーステーブルを自分で設計しなければならないということです。

OpenID Connect をサポートするためには、認可サーバー・OpenID プロバイダーは『[3. OpenID Provider Metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata)』（[OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)）にリストアップされているメタ情報を持つべきですし、クライアントアプリケーションは『[2. Client Metadata](https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata)』（[OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html)）にリストアップされているメタ情報を持つべきです。しかしながら、Spring Security OAuth は OpenID Connect をサポートしていないので、Spring Security OAuth 上に OpenID Connect を実装しようと試みない限り、これらのメタ情報に対応するカラムをデータベーステーブルに含める必要はありません。


# **3. 技術詳細**

### **3.1. Authlete API にアクセスするための API キー**

Authlete API にアクセスするための API キーと API シークレットを取得し、spring-oauth-server と spring-resource-server の `authlete.properties` に設定する必要があります。

簡単です。[アカウント登録ページ](https://so.authlete.com/accounts/signup)でアカウント登録するだけです。アカウント登録時に、一つのサービス（認可サーバー・OpenID プロバイダーに対応するもの）と、そのサービスに属するクライアントアプリケーションが一つ、自動的に生成されます。そのサービスの API キーと API シークレットは、管理コンソール（[Service Owner Console](https://www.authlete.com/documents/so_console)）で確認できます。

<img width="904" alt="from-signup-to-service-details.png" src="https://qiita-image-store.s3.amazonaws.com/0/106044/f14c6c7a-2659-778d-0976-74c7e5a8dd4f.png">


### **3.2. クライアント ID**

認可リクエストを実行するには、クライアントアプリケーションのクライアント ID を知る必要があります。Authlete はクライアントアプリケーション管理用のウェブコンソール（[Developer Console](https://www.authlete.com/documents/cd_console)）を用意しています。そのウェブコンソールの URL は `https://cd.authlete.com/{サービスAPIキー}` で、`{サービスAPIキー}`はクライアントアプリケーションが属するサービスの API キーです。ウェブコンソールにはサービスの API キーと API シークレットでログインすることができ、クライアント ID はそこで確認することができます。

<img width="967" alt="from-so_console_to-cd_console-client_id.png" src="https://qiita-image-store.s3.amazonaws.com/0/106044/46405e8e-f2cf-6394-a545-b4812480a17f.png">


### **3.3. 認可サーバー・OpenID プロバイダー**

まず、spring-oauth-server をダウンロードします。

```shell-session
$ git clone https://github.com/authlete/spring-oauth-server
```

次に、テキストエディタで設定ファイル `authlete.properties` を開き、`service.api_key` と `service.api_secret` の値を変更します。

```shell-session
$ cd spring-oauth-server
$ vi authlete.properties
```

最後に、spring-oauth-server を起動します。

```
$ mvn spring-boot:run
```


### **3.4. 認可リクエスト**

spring-oauth-server は `/api/authorization` で認可エンドポイントを公開しています。認可リクエストの `response_type` リクエストパラメーターの値が `token id_token` の場合、認可エンドポイントから直接、アクセストークンと ID トークンの両方が発行されます。OpenID Connect のフローにあまり詳しくない場合は『[OpenID Connect 全フロー解説](https://qiita.com/TakahikoKawasaki/items/4ee9b55db9f7ef352b47)』を参照してください。

下記はアクセストークンと ID トークンの両方を取得するための認可リクエストの例です。

```
http://localhost:8080/api/authorization
    ?client_id={クライアントID}
    &response_type=token+id_token
    &scope=openid
    &redirect_uri={リダイレクトURI}
    &state={任意文字列}
    &nonce={任意文字列}
```

もちろん、`{クライアントID}`、`{リダイレクトURI}`、`{任意文字列}` の値は置き換えてください。クライアントアプリケーションのリダイレクト URI の値は Developer Console で確認できます。デフォルト値を変更していなければ、リダイレクト URI は `https://api.authlete.com/api/mock/redirection/{サービスAPIキー}` になっています。

認可エンドポイントは認可ページを返します。ログインフォームがあるので、ログイン ID とパスワードとして、`john` と `john`（もしくは `jane` と `jane`）を入力してください。それから『Authorize』ボタンを押します。この結果、ウェブブラウザはクライアントアプリケーションのリダイレクト URI にリダイレクトされます。

リダイレクト URI のデフォルト値を変更していなければ、Authlete サーバーが提供するリダイレクトエンドポイントのモック実装にリダイレクトされます。そのモック実装は受け取ったパラメーターを表示するので、発行されたアクセストークンと ID トークンの値をその場で確認することができます。

<img width="850" alt="from-authorization_request-to-redirection_endpoint.png" src="https://qiita-image-store.s3.amazonaws.com/0/106044/e7db6026-ce7d-b526-0cdb-ab44ac0ccb9c.png">


### **3.5. リソースサーバー**

アクセストークンが取得できたので、保護リソースエンドポイントへの API コールを実行することができます。しかしその前に、リソースサーバーを起動する必要があります。

まず、spring-resource-server をダウンロードします。

```shell-session
$ git clone https://github.com/authlete/spring-resource-server
```

次に、テキストエディタで設定ファイル `authlete.properties` を開き、`service.api_key` と `service.api_secret` の値を変更します。

```shell-session
$ cd spring-resource-server
$ vi authlete.properties
```

最後に、spring-resource-server を起動します。

```
$ mvn spring-boot:run
```


### **3.6. API コール**

spring-resource-server が提供する保護リソースエンドポイントのサンプルに対して API コールを実行する準備が整いました。もちろん、`{アクセストークン}`はアクセストークンの実際の値で置き換えてください。

```shell-session
$ curl http://localhost:8081/api/country/JP \
    -d access_token={アクセストークン}
```

おめでとうございます。全ての手順が完了しました。


# **次のステップ**

1. spring-oauth-server と spring-resource-server の `README.md` と `CUSTOMIZATION.md` を参照してください。

2. [java-oauth-server](https://github.com/authlete/java-oauth-server) と [java-resource-server](https://github.com/authlete/java-resource-server) は JAX-RS API だけを用いた実装です。spring-oauth-server や spring-resource-server よりも、これらの実装のほうに興味をもたれるかもしれません。


# **さいごに**

認可サーバー・OpenID プロバイダーの実装をお探しなら、**[Authlete](https://www.authlete.com/)** をご検討ください。『[OAuth 2.0 / OIDC 実装の新アーキテクチャー](https://qiita.com/TakahikoKawasaki/items/b2a4fc39e0c1a1949aab)』を読めば、Authlete のアークテクチャーを好きになっていただけると思います :wink: