OAuth2.0 and Dynamic Client Registration
1. 前書き
このチュートリアルでは、OAuth2.0を使用した動的なクライアント登録を準備します。 OAuth2.0は、HTTPサービスのユーザーアカウントへの制限されたアクセスの取得を可能にする承認フレームワークです。 OAuth2.0クライアントは、ユーザーのアカウントにアクセスしたいアプリケーションです。 このクライアントは、外部Webアプリケーション、ユーザーエージェント、またはネイティブクライアントになります。
動的なクライアント登録を実現するために、ハードコードされた構成ではなく、資格情報をデータベースに保存します。 拡張するアプリケーションは、最初はSpring REST API + OAuth2 tutorialで記述されていました。
2. Mavenの依存関係
最初に、次の依存関係セットを設定します。
org.springframework.boot
spring-boot-starter-web
org.springframework
spring-jdbc
org.springframework.security.oauth
spring-security-oauth2
新しく登録したユーザーをパスワードで保存するためにDBを使用するため、spring-jdbcを使用していることに注意してください。
3. OAuth2.0 Server Configuration
まず、OAuth 2.0認証サーバーを設定する必要があります。 主な構成は、次のクラス内にあります。
@Configuration
@PropertySource({ "classpath:persistence.properties" })
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig
extends AuthorizationServerConfigurerAdapter {
// config
}
構成する必要のある主要なものがいくつかあります。 ClientDetailsServiceConfigurer:から始めましょう
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource())
// ...
}
これにより、永続性を使用してクライアント情報を取得していることを確認できます。
もちろん、この標準データソースを設定しましょう。
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
そのため、アプリケーションでは、通常のハードコーディングされたメモリクライアントではなく、データベースを登録済みクライアントのソースとして使用します。
4. DBスキーム
次に、OAuthクライアントを保存するためのSQL構造を定義しましょう。
create table oauth_client_details (
client_id VARCHAR(256) PRIMARY KEY,
resource_ids VARCHAR(256),
client_secret VARCHAR(256),
scope VARCHAR(256),
authorized_grant_types VARCHAR(256),
web_server_redirect_uri VARCHAR(256),
authorities VARCHAR(256),
access_token_validity INTEGER,
refresh_token_validity INTEGER,
additional_information VARCHAR(4096),
autoapprove VARCHAR(256)
);
焦点を当てるべきoauth_client_detailsの最も重要なフィールドは次のとおりです。
-
client_id –新しく登録されたクライアントのIDを保存します
-
client_secret –クライアントのパスワードを保存します
-
access_token_validity –クライアントがまだ有効かどうかを示します
-
authorities –特定のクライアントで許可されている役割を示します
-
scope –許可されたアクション(Facebookでのステータスの書き込みなど)。
-
authorized_grant_typesは、ユーザーが特定のクライアントにログインする方法に関する情報を提供します(この例では、パスワードを使用したフォームログインです)。
各クライアントはユーザーと1対多の関係を持っていることに注意してください。これは、当然、multiple users can utilize a single clientを意味します。
5. 一部のクライアントを永続化しましょう
SQLスキーマ定義を使用して、最終的にシステムにデータを作成し、基本的にクライアントを定義できます。
次のdata.sqlスクリプト(Spring Bootがデフォルトで実行する)を使用して、DBを初期化します。
INSERT INTO oauth_client_details
(client_id, client_secret, scope, authorized_grant_types,
web_server_redirect_uri, authorities, access_token_validity,
refresh_token_validity, additional_information, autoapprove)
VALUES
("fooClientIdPassword", "secret", "foo,read,write,
"password,authorization_code,refresh_token", null, null, 36000, 36000, null, true);
oauth_client_detailsの最も重要なフィールドの説明は、前のセクションで提供されています。
6. テスト
動的クライアント登録をテストするには、8081ポートと8082ポートで、それぞれspring-security-oauth-serverプロジェクトとspring-security-oauth-resourceプロジェクトの両方を実行する必要があります。
これで、最終的にいくつかのライブテストを作成できます。
foosを読み取るためのアクセス権を持つfooClientIdPasswordという名前のクライアントを登録したと仮定します。
まず、定義済みのクライアントを使用して、認証サーバーからアクセストークンを取得しようとします。
@Test
public void givenDBUser_whenRevokeToken_thenAuthorized() {
String accessToken = obtainAccessToken("fooClientIdPassword", "john", "123");
assertNotNull(accessToken);
}
そして、アクセストークンを取得するロジックは次のとおりです。
private String obtainAccessToken(String clientId, String username, String password) {
Map params = new HashMap();
params.put("grant_type", "password");
params.put("client_id", clientId);
params.put("username", username);
params.put("password", password);
Response response = RestAssured.given().auth().preemptive()
.basic(clientId, "secret").and().with().params(params).when()
.post("http://localhost:8081/spring-security-oauth-server/oauth/token");
return response.jsonPath().getString("access_token");
}
7. 結論
このチュートリアルでは、無制限の数のクライアントをOAuth2.0フレームワークに動的に登録する方法を学びました。
このチュートリアルの完全な実装はover on GitHubにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。
テストするには、クライアントをDBに追加する必要があり、.inMemory()構成は無効になることに注意してください。 古い。inMemory()構成を使用する場合は、ハードコードされたクライアントの構成を含む2番目のファイルがあります。