Spring + Authlete で OAuth / API サーバーを超速で構築する

# 概要
[Spring Boot](https://spring.io/projects/spring-boot) + [Authlete](https://www.authlete.com) を利用して、OAuth 2.0 / API サーバーを超速で構築する方法を解説します。

# アーキテクチャ

![](https://storage.googleapis.com/zenn-user-upload/865ecde5ad81-20240422.png)

# 手順

## 1. Authlete にサインアップ

[サインアップページ](https://so.authlete.com/accounts/signup)から、Authlete にサインアップします。

<img width="300" src="https://storage.googleapis.com/zenn-user-upload/fbb80be3d619-20240421.png">

サインアップが成功すると、サービスオーナーコンソールに自動ログインされます。

## 2. サービス作成＆設定

サービスオーナーコンソールにログイン後、「サービス作成」タブをクリックします。

![]()
<img width="500" src="https://storage.googleapis.com/zenn-user-upload/67879bb18bc2-20240421.png">

サービス作成画面上の「サービス名」を適当に入力後、作成ボタンをクリックしてサービスを作成します。

![](https://storage.googleapis.com/zenn-user-upload/ec39bde548e7-20240421.png)

その後、サービス詳細画面にて表示される **API キー**と **API シークレット**の値をメモしておきます。

![](https://storage.googleapis.com/zenn-user-upload/4a860f144864-20240421.png)

## 3. クライアント作成＆設定

下記 URL より、クライアント管理コンソールにアクセスします。

```
https://cd.authlete.com/{サービス API キーの値}
```

`(ログイン ID, パスワード) = (サービス API キー, サービス API シークレット)` として、クライアント管理コンソールにログインします。

<img width="400" src="https://storage.googleapis.com/zenn-user-upload/67fb4b399ddd-20240421.png">

クライアント作成画面上の「クライアント名」を適当に入力後、作成ボタンをクリックしてクライアントアプリを作成します。

![](https://storage.googleapis.com/zenn-user-upload/2afe23522be5-20240421.png)

その後、サービス詳細画面にて表示される **クライアント ID** の値をメモしておきます。

![](https://storage.googleapis.com/zenn-user-upload/a178b024b6b8-20240421.png)

## 4. 認可 (OAuth) サーバーのセットアップ

下記コマンドで、ソースコードをダウンロードします。

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

`authlete.properties` 内の項目を以下のように編集します。

```
service.api_key = (サービス API キー)
service.api_secret = (サービス API シークレット)
```

下記コマンドで認可 (OAuth) サーバーを起動します。　 (ポート 8080 で起動します。)

```bash
$ docker-compose up
```

## 5. API サーバーのセットアップ

下記コマンドで、ソースコードをダウンロードします。

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

`authlete.properties` 内の項目を以下のように編集します。

```
service.api_key = (サービス API キー)
service.api_secret = (サービス API シークレット)
```

下記コマンドで認可 API サーバーを起動します。　 (ポート 8081 で起動します。)

```bash
$ docker-compose up
```

## 6. 動作確認

### 6.1. アクセストークンの発行
では、認可コードフロー ([RFC6749](https://datatracker.ietf.org/doc/html/rfc6749)) を用いて、実際に認可サーバーからアクセストークンが発行されることを確認しましょう。

#### 6.1.1. 認可リクエスト
最初に、以下の URL (認可エンドポイント) にブラウザでアクセスします。

```bash
http://localhost:8080/api/authorization?client_id={クライアント ID}&response_type=code
```

すると以下のような認可画面が表示されます。

<img width="400" src="https://storage.googleapis.com/zenn-user-upload/668c82917c44-20240421.png">

下記のダミーユーザー情報を入力して **Authorize** ボタンを押します。

- User ID = john
- Password = john

:::message
ダミーユーザー情報は、`/src/main/java/com/authlete/spring/server/db/UserDao.java` にて管理されています。必要に応じてカスタマイズしてください。
:::

その後、下記のような URL リダイレクトされるので、クエリパラメーター `code` の値 (認可コード) をメモしておきます。

```
https://api.authlete.com/api/mock/redirection/{サービス API キー}?code=xxxxx...
```

#### 6.1.2. トークンリクエスト

続いて、上記で取得した認可コードを用いて、トークンエンドポイントにリクエストを送信します。以下はトークンリクエストの例です。

```bash
$ curl -v -X POST \
-d 'code={認可コードの値}' \
-d 'client_id={クライアント ID}' \
-d 'grant_type=authorization_code' \
http://localhost:8080/api/token
```

すると、以下のような成功レスポンスが得られます。

```json
{
  "access_token": "xxxxx",
  "refresh_token": "xxxxx",
  "scope": null,
  "token_type": "Bearer",
  "expires_in": 86400
}
```

### 6.2. API アクセス

それでは、6.1. で取得したアクセストークンを用いて API サーバー上の「API Country エンドポイント (`/api/country/{country-code}`)」にアクセスしてみましょう。

```bash
$ curl -v -H "Authorization: Bearer {access-token}" \
http://localhost:8081/api/country/JP
```

成功すると, 以下のような成功レスポンスが得られます。

```json
{
  "name": "Japan",
  "alpha2": "JP",
  "alpha3": "JPN",
  "numeric": 392,
  "currency": "JPY"
}
```

また, アクセストークンを付与せずにアクセスすると

```
$ curl -v http://localhost:8081/api/country/JP
```

以下のように、適切なエラーが返却されます。

```bash
< HTTP/1.1 400 
< Cache-Control: no-store, no-transform
< Pragma: no-cache
< WWW-Authenticate: Bearer error="invalid_token",error_description="An access token is missing."
< Content-Length: 0
...
```

## More Info

更に詳細を知りたい、カスタマイズしたい方は、下記資料をご参照ください。

- spring-oauth-server の [README.md](https://github.com/authlete/spring-oauth-server/blob/master/README.md) と [CUSTOMIZATION.md](https://github.com/authlete/spring-oauth-server/blob/master/doc/CUSTOMIZATION.md) 
- spring-resource-server の [README.md](https://github.com/authlete/spring-resource-server/blob/master/README.md) と [CUSTOMIZATION.md](https://github.com/authlete/spring-resource-server/blob/master/doc/CUSTOMIZATION.md)

## 最後に

![authlete-logo-horizontal_wclear.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60350/8e160e92-83f6-34fb-f718-3ada9db8b87b.png)

最後に、私が共同創業した [Authlete, Inc.](https://www.authlete.com/) は OAuth サーバー/OpenID Connect プロバイダーを構築するための [Web API](https://docs.authlete.com) 提供しております。世界中の専門家をメンバーに抱え、FAPI 等の OpenID 認定も取得済みです。

ご興味がある場合、[こちらのウェブフォーム](https://www.authlete.com/contact/)または以下のメールアドレスよりお気軽にお問い合わせください。

- **ライセンスおよび契約**: [sales@authlete.com](mailto:sales@authlete.com)
- **パートナーシップ**: [bizdev@authlete.com](mailto:bizdev@authlete.com)
- **技術サポート**: [support@authlete.com](mailto:support@authlete.com)

また、下記のチェックも是非よろしくお願い致します。

- [GitHub](https://github.com/authlete)
- [Qiita](https://qiita.com/organizations/authlete)
- [Zenn](https://zenn.dev/p/authlete)
- [Facebook](https://www.facebook.com/authlete)
- [X (Twitter)](https://twitter.com/authlete)
- [Linkedin](https://www.linkedin.com/company/authlete)
- [YouTube](https://www.youtube.com/channel/UCERMcUO2vR7F96Qd-BZbiwA)

最後までご拝読頂きありがとうございました。