Spring Cloud Azure での Spring Security のサポート
この記事は、✅ バージョン 4.19.0 ✅ バージョン 5.19.0 に適用されます。
この記事では、Spring Cloud Azure と Spring Security を組み合わせて使用する方法について説明します。
Microsoft Entra ID を使用した Spring Security
Web アプリケーションを構築する場合、ID とアクセスの管理は常に基礎となります。
Azure は、クラウドベースの ID サービスだけでなく、Azure エコシステムの残りの部分との緊密な統合も提供するため、アプリケーション開発の過程を民主化するための優れたプラットフォームを提供します。
Spring Security を使用すると、強力な抽象化と拡張可能なインターフェイスを使用して、Spring ベースのアプリケーションを簡単にセキュリティで保護できます。 ただし、Spring フレームワークと同じくらい強力な機能は、特定の ID プロバイダーに合わせて調整されるわけではありません。
spring-cloud-azure-starter-active-directory
は、Web アプリケーションを Microsoft Entra ID (短い場合は Microsoft Entra ID) テナントに接続し、Microsoft Entra ID でリソース サーバーを保護するための最適な方法を提供します。 Oauth 2.0 プロトコルを使用して、Web アプリケーションとリソース サーバーを保護します。
Web アプリケーションへのアクセス
このシナリオでは、OAuth 2.0 認証コード許可 フローを使用して、Microsoft アカウントを使用してユーザーにログインします。
システム図
Azure で必要なリソースを作成する
クイック スタート 読む: アプリケーションを Microsoft ID プラットフォームに登録します。
アプリの登録を作成します。
AZURE_TENANT_ID
、AZURE_CLIENT_ID
、およびAZURE_CLIENT_SECRET
を取得します。redirect URI
をAPPLICATION_BASE_URI/login/oauth2/code/
に設定します (例:http://localhost:8080/login/oauth2/code/
)。 尾/
が必要です。
必要な依存関係を追加する
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
必要なプロパティを追加する
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: <tenant>
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
次に、アプリケーションを起動し、ブラウザーからアプリケーションにアクセスします。 Microsoft ログイン ページにリダイレクトされます。
高度な使用方法
追加のセキュリティ構成を追加する
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2LoginSecurityConfig {
/**
* Add configuration logic as needed.
*/
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
.and()
.authorizeHttpRequests()
.anyRequest().authenticated();
// Do some custom configuration.
return http.build();
}
}
アプリ ロールによるアクセスを承認する
Azure で必要なリソースを作成します。
アプリケーションにアプリ ロールを追加し、トークンで受け取ります。
次のパラメーターを使用してアプリ ロールを作成します。
- 表示名: 管理者
- 許可されるメンバーの種類: ユーザー/グループ
- 値: 管理者
- このアプリ ロールを有効にしますか: はい
手記
アプリロールベースのアクセス制御を使用する場合は、role
要求にグループ名を含めることはできません。 詳細については、「アプリに省略可能な要求を提供する」の「グループの省略可能な要求 の構成」セクションを参照してください。
特定のメソッドを保護します。
class Demo {
@GetMapping("Admin")
@ResponseBody
@PreAuthorize("hasAuthority('APPROLE_Admin')")
public String admin() {
return "Admin message";
}
}
グループ名またはグループ ID でアクセスを承認する
関連する構成プロパティを追加します。
spring:
cloud:
azure:
active-directory:
enabled: true
user-group:
allowed-group-names: group1_name_1, group2_name_2
# 1. If allowed-group-ids == all, then all group ID will take effect.
# 2. If "all" is used, we should not configure other group ids.
# 3. "all" is only supported for allowed-group-ids, not supported for allowed-group-names.
allowed-group-ids: group_id_1, group_id_2
特定のメソッドを保護します。
@Controller
public class RoleController {
@GetMapping("group1")
@ResponseBody
@PreAuthorize("hasRole('ROLE_group1')")
public String group1() {
return "group1 message";
}
@GetMapping("group2")
@ResponseBody
@PreAuthorize("hasRole('ROLE_group2')")
public String group2() {
return "group2 message";
}
@GetMapping("group1Id")
@ResponseBody
@PreAuthorize("hasRole('ROLE_<group1-id>')")
public String group1Id() {
return "group1Id message";
}
@GetMapping("group2Id")
@ResponseBody
@PreAuthorize("hasRole('ROLE_<group2-id>')")
public String group2Id() {
return "group2Id message";
}
}
グローバル Azure ではなく National Azure を使用する
グローバル Azure クラウドを除き、Microsoft Entra ID は次の国内クラウドにデプロイされます。
Azure Government
Azure China 21Vianet
Azure Germany
Azure China 21Vianet を使用したサンプルを次に示します。
spring:
cloud:
azure:
active-directory:
enabled: true
base-uri: https://login.partner.microsoftonline.cn
graph-base-uri: https://microsoftgraph.chinacloudapi.cn
詳細については、「国内クラウドデプロイ
リダイレクト URI テンプレートを構成する
開発者はリダイレクト URI をカスタマイズできます。
redirect-uri-template
ファイル プロパティを追加します。
spring:
cloud:
azure:
active-directory:
enabled: true
redirect-uri-template: ${REDIRECT-URI-TEMPLATE}
Azure portal で redirect-uri
を更新します。
redirect-uri-template
設定した後、セキュリティ ビルダーを更新する必要があります。
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2LoginSecurityConfig {
/**
* Add configuration logic as needed.
*/
@Bean
public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
.and()
.oauth2Login()
.loginProcessingUrl("${REDIRECT-URI-TEMPLATE}")
.and()
.authorizeHttpRequests()
.anyRequest().authenticated();
// @formatter:on
return http.build();
}
}
プロキシ経由で Microsoft Entra ID に接続する
プロキシ経由で Microsoft Entra ID を接続するには、次の例に示すような RestTemplateCustomizer
Bean を指定します。
@Configuration
class DemoConfiguration {
@Bean
public RestTemplateCustomizer proxyRestTemplateCustomizer() {
return (RestTemplate restTemplate) -> {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_SERVER_HOST, PROXY_SERVER_PORT));
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setProxy(proxy);
restTemplate.setRequestFactory(requestFactory);
};
}
}
サンプル
サンプル プロジェクト: aad-web-applicationを
リソース サーバーにアクセスする Web アプリケーション
システム図
Azure で必要なリソースを作成する
クイック スタート 読む: アプリケーションを Microsoft ID プラットフォームに登録します。
アプリの登録を作成します。
AZURE_TENANT_ID
、AZURE_CLIENT_ID
、およびAZURE_CLIENT_SECRET
を取得します。redirect URI
など、APPLICATION_BASE_URI/login/oauth2/code/
をhttp://localhost:8080/login/oauth2/code/
に設定します。 尾/
が必要です。
必要な依存関係を追加する
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
必要なプロパティを追加する
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: <tenant>
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
graph:
scopes: https://graph.microsoft.com/Analytics.Read, email
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
ここで、graph
は OAuth2AuthorizedClient
の名前です。scopes
ログイン時に同意するために必要なスコープを意味します。
アプリケーションで OAuth2AuthorizedClient を使用する
public class Demo {
@GetMapping("/graph")
@ResponseBody
public String graph(
@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graphClient) {
// toJsonString() is just a demo.
// oAuth2AuthorizedClient contains access_token. We can use this access_token to access resource server.
return toJsonString(graphClient);
}
}
次に、アプリケーションを起動し、ブラウザーでアプリケーションにアクセスします。 その後、Microsoft ログイン ページにリダイレクトされます。
高度な使用方法
クライアント資格情報フロー
既定のフローは認証コード フロー
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: <tenant>
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
graph:
authorization-grant-type: client_credentials # Change type to client_credentials
scopes: https://graph.microsoft.com/Analytics.Read, email
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
複数のリソース サーバーにアクセスする
1 つの Web アプリケーションで、次のように構成することで、複数のリソース サーバーにアクセスできます。
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: <tenant>
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
resource-server-1:
scopes: # Scopes for resource-server-1
resource-server-2:
scopes: # Scopes for resource-server-2
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
その後、次のようなアプリケーションで OAuth2AuthorizedClient
を使用できます
public class Demo {
@GetMapping("/resource-server-1")
@ResponseBody
public String graph(
@RegisteredOAuth2AuthorizedClient("resource-server-1") OAuth2AuthorizedClient client) {
return callResourceServer1(client);
}
@GetMapping("/resource-server-2")
@ResponseBody
public String graph(
@RegisteredOAuth2AuthorizedClient("resource-server-2") OAuth2AuthorizedClient client) {
return callResourceServer2(client);
}
}
サンプル
サンプル プロジェクト: aad-web-applicationを
リソース サーバーへのアクセス
このシナリオでは、ログインはサポートされていません。アクセス トークンを検証してサーバーを保護するだけです。 アクセス トークンが有効な場合、サーバーは要求を処理します。
システム図
Azure で必要なリソースを作成する
クイック スタート 読む: アプリケーションを Microsoft ID プラットフォームに登録します。
アプリの登録を作成します。
AZURE_CLIENT_ID
を取得します。クイック スタート 読む: Web APIを公開するようにアプリケーションを構成する。
Scope-1
という名前のスコープを持つ Web API を公開します。
必要な依存関係を追加する
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
</dependencies>
必要なプロパティを追加する
spring:
cloud:
azure:
active-directory:
enabled: true
credential:
client-id: ${AZURE_CLIENT_ID}
次に、アプリケーションを起動し、アプリケーションの Web API にアクセスします。
アクセス トークンなしで 401 を取得します。
アクセス トークンを使用してアプリケーションにアクセスします。 アクセス トークン内の次の要求が検証されます。
iss
: アクセス トークンは Microsoft Entra ID によって発行される必要があります。nbf
: 現在の時刻をnbf
前にすることはできません。exp
: 現在の時刻はexp
後にできません。aud
:spring.cloud.azure.active-directory.credential.client-id
またはspring.cloud.azure.active-directory.credential.app-id-uri
構成されている場合、対象ユーザーは構成されたclient-id
またはapp-id-uri
と等しい必要があります。 2 つのプロパティが構成されていない場合、この要求は検証されません。
アクセス トークンの詳細については、Microsoft ID プラットフォーム アクセス トークン
高度な使用方法
追加のセキュリティ構成を追加する
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadOAuth2ResourceServerSecurityConfig {
/**
* Add configuration logic as needed.
*/
@Bean
public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http.apply(AadResourceServerHttpSecurityConfigurer.aadResourceServer())
.and()
.authorizeHttpRequests()
.anyRequest().authenticated();
// @formatter:on
return http.build();
}
}
スコープ別にアクセス許可を検証する
Azure で必要なリソースを作成します。
クイック スタート 読む: Web APIを公開するようにアプリケーションを構成する。
Scope1
という名前のスコープを持つ Web API を公開します。
特定のメソッドを保護します。
class Demo { @GetMapping("scope1") @ResponseBody @PreAuthorize("hasAuthority('SCOPE_Scope1')") public String scope1() { return "Congratulations, you can access `scope1` endpoint."; } }
これにより、エンドポイント /scope1
アクセスするときに、アクセス トークン内の次の要求が検証されます。
-
scp
: 値にはScope1
を含む必要があります。
アプリ ロール別のアクセス許可を検証する
Azure で必要なリソースを作成します。
アプリケーションにアプリ ロールを追加し、トークンで受け取ります。
次のパラメーターを使用してアプリ ロールを作成します。
- 表示名: AppRole1
- 許可されるメンバーの種類: ユーザー/グループ
- 値: AppRole1
- このアプリ ロールを有効にしますか: はい
特定のメソッドを保護します。
class Demo { @GetMapping("app-role1") @ResponseBody @PreAuthorize("hasAuthority('APPROLE_AppRole1')") public String appRole1() { return "Congratulations, you can access `app-role1` endpoint."; } }
これにより、エンドポイント /app-role1
アクセスするときに、アクセス トークン内の次の要求が検証されます。
-
roles
: 値にはAppRole1
を含む必要があります。
JWT クライアント認証を使用する
クライアント認証に JSON Web トークン (JWT) を使用するには、次の手順を使用します。
- Microsoft ID プラットフォーム アプリケーション認証証明書資格情報 の「証明書を Microsoft ID プラットフォーム に登録する」セクションを参照してください。
- .pem 証明書を、Azure portal に登録されているアプリケーションにアップロードします。
- の証明書パスとパスワードを構成します。PFX または 。P12 証明書。
- JWT クライアント認証を使用して認証するプロパティ
spring.cloud.azure.active-directory.authorization-clients.azure.client-authentication-method=private_key_jwt
構成をクライアントに追加します。
次の構成ファイルの例は、Web アプリケーションシナリオ用です。 証明書情報は、グローバル プロパティで構成されます。
spring:
cloud:
azure:
credential:
client-id: ${AZURE_CLIENT_ID}
client-certificate-path: ${AZURE_CERTIFICATE_PATH}
client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
profile:
tenant-id: <tenant>
active-directory:
enabled: true
user-group:
allowed-group-names: group1,group2
allowed-group-ids: <group1-id>,<group2-id>
post-logout-redirect-uri: http://localhost:8080
authorization-clients:
azure:
client-authentication-method: private_key_jwt
arm:
client-authentication-method: private_key_jwt
scopes: https://management.core.windows.net/user_impersonation
graph:
client-authentication-method: private_key_jwt
scopes:
- https://graph.microsoft.com/User.Read
- https://graph.microsoft.com/Directory.Read.All
webapiA:
client-authentication-method: private_key_jwt
scopes:
- ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
webapiB:
client-authentication-method: private_key_jwt
scopes:
- ${WEB_API_B_APP_ID_URL}/.default
authorization-grant-type: client_credentials
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
次の例に示すように、active-directory
サービスのプロパティで証明書情報を構成することもできます。
spring:
cloud:
azure:
active-directory:
enabled: true
credential:
client-id: ${AZURE_CLIENT_ID}
client-certificate-path: ${AZURE_CERTIFICATE_PATH}
client-certificate-password: ${AZURE_CERTIFICATE_PASSWORD}
profile:
tenant-id: <tenant>
user-group:
allowed-group-names: group1,group2
allowed-group-ids: <group1-id>,<group2-id>
post-logout-redirect-uri: http://localhost:8080
authorization-clients:
azure:
client-authentication-method: private_key_jwt
arm:
client-authentication-method: private_key_jwt
scopes: https://management.core.windows.net/user_impersonation
graph:
client-authentication-method: private_key_jwt
scopes:
- https://graph.microsoft.com/User.Read
- https://graph.microsoft.com/Directory.Read.All
webapiA:
client-authentication-method: private_key_jwt
scopes:
- ${WEB_API_A_APP_ID_URL}/Obo.WebApiA.ExampleScope
webapiB:
client-authentication-method: private_key_jwt
scopes:
- ${WEB_API_B_APP_ID_URL}/.default
authorization-grant-type: client_credentials
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
プロキシ経由で Microsoft Entra ID に接続する
プロキシ経由で Microsoft Entra ID を接続するには、RestTemplateCustomizer
Bean を指定します。 詳細については、「プロキシを使用した Microsoft Entra ID への接続 」セクションを参照してください。
サンプル
サンプル プロジェクト: aad-resource-serverを
他のリソース サーバーにアクセスするリソース サーバー
システム図
Azure で必要なリソースを作成する
クイック スタート 読む: アプリケーションを Microsoft ID プラットフォームに登録します。
アプリの登録を作成します。
AZURE_TENANT_ID
、AZURE_CLIENT_ID
、およびAZURE_CLIENT_SECRET
を取得します。
必要な依存関係を追加する
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
必要なプロパティを追加する
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: <tenant>
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
authorization-clients:
graph:
scopes:
- https://graph.microsoft.com/User.Read
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
アプリケーションで OAuth2AuthorizedClient を使用する
public class SampleController {
@GetMapping("call-graph")
public String callGraph(@RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient graph) {
return callMicrosoftGraphMeEndpoint(graph);
}
}
サンプル
サンプル プロジェクト: aad-resource-server-oboを
1 つのアプリケーション内の Web アプリケーションとリソース サーバー
Azure で必要なリソースを作成する
クイック スタート 読む: アプリケーションを Microsoft ID プラットフォームに登録します。
アプリの登録を作成します。
AZURE_TENANT_ID
、AZURE_CLIENT_ID
、およびAZURE_CLIENT_SECRET
を取得します。
必要な依存関係を追加する
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
</dependencies>
必要なプロパティを追加する
プロパティ spring.cloud.azure.active-directory.application-type
を web_application_and_resource_server
に設定し、各承認クライアントの承認の種類を指定します。
spring:
cloud:
azure:
active-directory:
enabled: true
profile:
tenant-id: <tenant>
credential:
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
app-id-uri: ${WEB_API_ID_URI}
application-type: web_application_and_resource_server # This is required.
authorization-clients:
graph:
authorizationGrantType: authorization_code # This is required.
scopes:
- https://graph.microsoft.com/User.Read
- https://graph.microsoft.com/Directory.Read.All
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
SecurityFilterChain の定義
複数の SecurityFilterChain
インスタンスを構成します。
AadWebApplicationAndResourceServerConfig
には、リソース サーバーと Web アプリケーション用の 2 つのセキュリティ フィルター チェーン構成が含まれています。
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class AadWebApplicationAndResourceServerConfig {
@Bean
@Order(1)
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
http.apply(AadResourceServerHttpSecurityConfigurer.aadResourceServer())
.and()
// All the paths that match `/api/**`(configurable) work as the resource server. Other paths work as the web application.
.securityMatcher("/api/**")
.authorizeHttpRequests()
.anyRequest().authenticated();
return http.build();
}
@Bean
public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
.and()
.authorizeHttpRequests()
.requestMatchers("/login").permitAll()
.anyRequest().authenticated();
// @formatter:on
return http.build();
}
}
構成
spring-cloud-azure-starter-active-directory の構成可能なプロパティ:
名前 | 形容 |
---|---|
spring.cloud.azure.active-directory.app-id-uri を |
id_tokenの "aud" 要求で使用される可能性があるアプリ ID URI。 |
spring.cloud.azure.active-directory.application-type | Microsoft Entra アプリケーションの種類。 |
spring.cloud.azure.active-directory.authenticate-additional-parameters を |
承認 URL にパラメーターを追加します。 |
spring.cloud.azure.active-directory.authorization-clients を |
OAuth2 承認クライアント。 |
spring.cloud.azure.active-directory.credential.client-id を |
Azure でサービス プリンシパル認証を実行するときに使用するクライアント ID。 |
spring.cloud.azure.active-directory.credential.client-secret を |
Azure でサービス プリンシパル認証を実行するときに使用するクライアント シークレット。 |
spring.cloud.azure.active-directory.jwk-set-cache-有効期間 | キャッシュされた JWK セットの有効期限が切れる前の有効期間は、既定値は 5 分です。 |
spring.cloud.azure.active-directory.jwk-set-cache-refresh-time を |
キャッシュされた JWK セットの更新時間は、有効期限が切れる前に 5 分です。 |
spring.cloud.azure.active-directory.jwt-connect-timeout | JWKSet リモート URL 呼び出しの接続タイムアウト。 |
spring.cloud.azure.active-directory.jwt-read-timeout を |
JWKSet リモート URL 呼び出しの読み取りタイムアウト。 |
spring.cloud.azure.active-directory.jwt-size-limit を |
JWKSet リモート URL 呼び出しのサイズ制限 (バイト単位)。 |
spring.cloud.azure.active-directory.post-logout-redirect-uri を |
ログアウト後のリダイレクト URI。 |
spring.cloud.azure.active-directory.profile.cloud-type | 接続する Azure クラウドの名前。 サポートされている種類は、AZURE、AZURE_CHINA、AZURE_GERMANY、AZURE_US_GOVERNMENT、その他です。 |
spring.cloud.azure.active-directory.profile.environment を |
Microsoft Entra エンドポイントのプロパティ。 |
spring.cloud.azure.active-directory.profile.tenant-id を |
Azure テナント ID。
tenant-id に使用できる値は、common 、organizations 、consumers 、またはテナント ID です。 |
spring.cloud.azure.active-directory.redirect-uri-template を |
リダイレクト エンドポイント: リソース所有者のユーザー エージェントを介して、承認資格情報を含む応答をクライアントに返すために承認サーバーによって使用されます。 既定値は {baseUrl}/login/oauth2/code/ です。 |
spring.cloud.azure.active-directory.resource-server.claim-to-authority-prefix-map の |
GrantedAuthority のビルドに使用する要求と、GrantedAuthority の文字列値のプレフィックスを構成します。 既定値は"scp" -> "SCOPE_"、"roles" -> "APPROLE_" です。 |
spring.cloud.azure.active-directory.resource-server.principal-claim-name を |
AuthenticatedPrincipal#getName で返されるアクセス トークン内の要求を構成します。 既定値は "sub" です。 |
spring.cloud.azure.active-directory.session-stateless を |
true の場合、ステートレス認証フィルター AadAppRoleStatelessAuthenticationFilter がアクティブになります。 既定値は false で、AadAuthenticationFilter をアクティブにします。 |
spring.cloud.azure.active-directory.user-group.allowed-group-ids を |
グループ ID を使用して、GrantedAuthority を構築できます。 |
spring.cloud.azure.active-directory.user-group.allowed-group-names を |
グループ名を使用して、GrantedAuthority を構築できます。 |
spring.cloud.azure.active-directory.user-group.use-transitive-members を |
"true" の場合は、"v1.0/me/transitiveMemberOf" を使用してメンバーを取得します。 それ以外の場合は、"v1.0/me/memberOf" を使用します。 既定値は false です。 |
spring.cloud.azure.active-directory.user-name-attribute を |
プリンシパルの名前にする要求を決定します。 |
これらのプロパティの使用方法の例を次に示します。
アプリケーションの種類
アプリケーションの種類は、依存関係 (spring-security-oauth2-client
または spring-security-oauth2-resource-server
) から推論できます。 推論された値が目的の値でない場合は、アプリケーションの種類を指定できます。 有効な値と推論された値の表を次に示します。
spring-cloud-azure-starter-active-directory
のアプリケーションの種類:
依存関係がある: spring-security-oauth2-client |
依存関係がある: spring-security-oauth2-resource-server |
アプリケーションの種類の有効な値 | 推論された値 |
---|---|---|---|
はい | いいえ | web_application |
web_application |
いいえ | はい | resource_server |
resource_server |
はい | はい |
web_application 、 resource_server 、 resource_server_with_obo 、 web_application_and_resource_server |
resource_server_with_obo |
Azure Active Directory B2C を使用した Spring Security
Azure Active Directory (Azure AD) B2C は ID 管理サービスであり、アプリケーションを使用する際の顧客のサインアップ、サインイン、およびプロファイルの管理方法をカスタマイズおよび制御できます。 Azure AD B2C では、顧客の ID を同時に保護しながら、これらのアクションを有効にします。
依存関係のセットアップ
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId>
</dependency>
</dependencies>
構成
spring-cloud-azure-starter-active-directory-b2c の構成可能なプロパティ:
名前 | 形容 |
---|---|
spring.cloud.azure.active-directory.b2c.app-id-uri | トークンの "aud" 要求で使用される可能性があるアプリ ID URI。 |
spring.cloud.azure.active-directory.b2c.authenticate-additional-parameters を |
認証用の追加パラメーター。 |
spring.cloud.azure.active-directory.b2c.authorization-clients を |
クライアント構成を指定します。 |
spring.cloud.azure.active-directory.b2c.base-uri の |
Azure AD B2C エンドポイントのベース URI。 |
spring.cloud.azure.active-directory.b2c.credential を |
Azure AD B2C 資格情報。 |
spring.cloud.azure.active-directory.b2c.jwt-connect-timeout | JWKSet リモート URL 呼び出しの接続タイムアウト。 |
spring.cloud.azure.active-directory.b2c.jwt-read-timeout の |
JWKSet リモート URL 呼び出しの読み取りタイムアウト。 |
spring.cloud.azure.active-directory.b2c.jwt-size-limit | JWKSet リモート URL 呼び出しのサイズ制限 (バイト単位)。 |
spring.cloud.azure.active-directory.b2c.login-flow | プライマリ サインイン フロー キーを指定します。 既定値は sign-up-or-sign-in です。 |
spring.cloud.azure.active-directory.b2c.logout-success-url を |
ログアウト後のリダイレクト URL。 既定値は http://localhost:8080/login です。 |
spring.cloud.azure.active-directory.b2c.profile を |
Azure AD B2C プロファイル情報。 |
spring.cloud.azure.active-directory.b2c.reply-url を |
承認コードを取得した後の応答 URL。 既定値は {baseUrl}/login/oauth2/code/ です。 |
spring.cloud.azure.active-directory.b2c.user-flows の |
ユーザー フロー。 |
spring.cloud.azure.active-directory.b2c.user-name-attribute-name を |
ユーザー名属性名。 |
完全な構成については、Spring Cloud の Azure 構成プロパティ 確認してください。
基本的な使用方法
Web アプリケーション は、ユーザーが Microsoft Entra ID でログインできる任意の Web ベースのアプリケーションですが、リソース サーバー は、Microsoft Entra ID から取得したaccess_token検証した後、アクセスを受け入れるか拒否します。 このガイドでは、次の 4 つのシナリオについて説明します。
Web アプリケーションへのアクセス。
リソース サーバーにアクセスする Web アプリケーション。
リソース サーバーへのアクセス。
他のリソース サーバーにアクセスするリソース サーバー。
使用法 1: Web アプリケーションへのアクセス
このシナリオでは、OAuth 2.0 認証コード許可 フローを使用して、Azure AD B2C ユーザーを使用してユーザーにログインします。
ポータル メニュー
アプリケーション 名前 (webapp
など) を指定し、http://localhost:8080/login/oauth2/code/
の を追加し、アプリケーション ID を WEB_APP_AZURE_CLIENT_ID
として記録して、[保存]を選択します。
アプリケーションから
左側
[サインアップ]、[]、[プロファイル編集
[
Graph アクセス許可に対して管理者の同意を付与します。
pom.xml ファイルに次の依存関係を追加します。
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
</dependencies>
次の例に示すように、前に作成した値を使用して、application.yml ファイルにプロパティを追加します。
spring:
cloud:
azure:
active-directory:
b2c:
enabled: true
authenticate-additional-parameters:
domain_hint: xxxxxxxxx # optional
login_hint: xxxxxxxxx # optional
prompt: [login,none,consent] # optional
base-uri: ${BASE_URI}
credential:
client-id: ${WEBAPP_AZURE_CLIENT_ID}
client-secret: ${WEBAPP_AZURE_CLIENT_SECRET}
login-flow: ${LOGIN_USER_FLOW_KEY} # default to sign-up-or-sign-in, will look up the user-flows map with provided key.
logout-success-url: ${LOGOUT_SUCCESS_URL}
user-flows:
${YOUR_USER_FLOW_KEY}: ${USER_FLOW_NAME}
user-name-attribute-name: ${USER_NAME_ATTRIBUTE_NAME}
Java コードを記述します。
コントローラー コードについては、次の例を参照できます。
@Controller
public class WebController {
private void initializeModel(Model model, OAuth2AuthenticationToken token) {
if (token != null) {
final OAuth2User user = token.getPrincipal();
model.addAllAttributes(user.getAttributes());
model.addAttribute("grant_type", user.getAuthorities());
model.addAttribute("name", user.getName());
}
}
@GetMapping(value = { "/", "/home" })
public String index(Model model, OAuth2AuthenticationToken token) {
initializeModel(model, token);
return "home";
}
}
セキュリティ構成コードについては、次の例を参照してください。
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
public class WebSecurityConfiguration {
private final AadB2cOidcLoginConfigurer configurer;
public WebSecurityConfiguration(AadB2cOidcLoginConfigurer configurer) {
this.configurer = configurer;
}
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.apply(configurer);
// @formatter:on
return http.build();
}
}
aad-b2c-web-application サンプルから home.html をコピーし、PROFILE_EDIT_USER_FLOW
と PASSWORD_RESET_USER_FLOW
を前に使用したユーザー フロー名に置き換えます。
アプリをビルドしてテストします。
Webapp
ポート 8080で実行します。
Maven によってアプリケーションがビルドおよび起動されたら、Web ブラウザーで http://localhost:8080/
を開きます。 ログイン ページにリダイレクトされます。
ログイン ユーザー フローを含むリンクを選択します。 認証プロセスを開始するには、Azure AD B2C にリダイレクトする必要があります。
正常にログインすると、ブラウザーからサンプル home page
が表示されます。
使用法 2: リソース サーバーにアクセスする Web アプリケーション
このシナリオは、アプリケーションが他のリソースにアクセスできるようにする Web アプリケーションへのアクセス シナリオに基づいています。 このシナリオは、OAuth 2.0 クライアント資格情報付与フロー
ポータル メニュー
アプリケーション
アプリケーションから
ナビゲーション ウィンドウ WEB_API_A_APP_ID_URL
として記録し、[保存] 選択。
ナビゲーション ウィンドウから [マニフェスト
{
"allowedMemberTypes": [
"Application"
],
"description": "WebApiA.SampleScope",
"displayName": "WebApiA.SampleScope",
"id": "04989db0-3efe-4db6-b716-ae378517d2b7",
"isEnabled": true,
"value": "WebApiA.SampleScope"
}
WebApiA アクセス許可
Web アプリケーションへのアクセスの シナリオに基づいて、次の依存関係を追加します。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Web アプリケーションへのアクセスの シナリオに基づいて、次の構成を追加します。
spring:
cloud:
azure:
active-directory:
b2c:
enabled: true
base-uri: ${BASE_URI} # Such as: https://xxxxb2c.b2clogin.com
profile:
tenant-id: <tenant>
authorization-clients:
${RESOURCE_SERVER_A_NAME}:
authorization-grant-type: client_credentials
scopes: ${WEB_API_A_APP_ID_URL}/.default
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
Webapp
Java コードを記述します。
コントローラー コードについては、次の例を参照できます。
class Demo {
/**
* Access to protected data from Webapp to WebApiA through client credential flow. The access token is obtained by webclient, or
* <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
* DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
*
* @return Respond to protected data from WebApi A.
*/
@GetMapping("/webapp/webApiA")
public String callWebApiA() {
String body = webClient
.get()
.uri(LOCAL_WEB_API_A_SAMPLE_ENDPOINT)
.attributes(clientRegistrationId("webApiA"))
.retrieve()
.bodyToMono(String.class)
.block();
LOGGER.info("Call callWebApiA(), request '/webApiA/sample' returned: {}", body);
return "Request '/webApiA/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
}
}
セキュリティ構成コードは、Web アプリケーションへのアクセス シナリオと同じです。 次のように、もう 1 つの Bean webClient
を追加します。
public class SampleConfiguration {
@Bean
public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction function =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
return WebClient.builder()
.apply(function.oauth2Configuration())
.build();
}
}
WebApiA
Java コードを記述するには、「リソース サーバーへのアクセス 」セクションを参照してください。
アプリをビルドしてテストします。 ポート Webapp
と WebApiA
で、 と をそれぞれ実行します。
Webapp
を起動し、アプリケーションを WebApiA
します。 正常にログインした後、ホーム ページに戻ります。 その後、http://localhost:8080/webapp/webApiA
にアクセスして、WebApiA
リソースの応答を取得できます。
使用法 3: リソース サーバーへのアクセス
このシナリオでは、ログインはサポートされていません。 アクセス トークンを検証してサーバーを保護するだけで、有効な場合は要求を処理します。
WebApiA
アクセス許可を作成するには、「使用法 2: リソース サーバーにアクセスする Web アプリケーション」を参照してください。
WebApiA
アクセス許可を追加し、Web アプリケーションの管理者の同意を付与します。
pom.xml ファイルに次の依存関係を追加します。
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
次の構成を追加します。
spring:
cloud:
azure:
active-directory:
b2c:
enabled: true
base-uri: ${BASE_URI} # Such as: https://xxxxb2c.b2clogin.com
profile:
tenant-id: <tenant>
app-id-uri: ${APP_ID_URI} # If you're using v1.0 token, configure app-id-uri for `aud` verification
credential:
client-id: ${AZURE_CLIENT_ID} # If you're using v2.0 token, configure client-id for `aud` verification
user-flows:
sign-up-or-sign-in: ${SIGN_UP_OR_SIGN_IN_USER_FLOW_NAME}
手記
tenant-id
に使用できる値は、common
、organizations
、consumers
、またはテナント ID です。 これらの値の詳細については、「エラー AADSTS50020 - ID プロバイダーのユーザー アカウントがテナントに存在しない」の「間違ったエンドポイント (個人用アカウントと組織アカウント) セクションを参照してください。 シングルテナント アプリの変換の詳細については、「Microsoft Entra IDでのシングルテナント アプリをマルチテナントに変換する」を参照してください。
Java コードを記述します。
コントローラー コードについては、次の例を参照できます。
class Demo {
/**
* webApiA resource api for web app
* @return test content
*/
@PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
@GetMapping("/webApiA/sample")
public String webApiASample() {
LOGGER.info("Call webApiASample()");
return "Request '/webApiA/sample'(WebApi A) returned successfully.";
}
}
セキュリティ構成コードについては、次の例を参照してください。
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@EnableMethodSecurity
public class ResourceServerConfiguration {
@Bean
public SecurityFilterChain htmlFilterChain(HttpSecurity http) throws Exception {
JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("APPROLE_");
authenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
// @formatter:off
http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(authenticationConverter);
// @formatter:on
return http.build();
}
}
アプリをビルドしてテストします。
WebApiA
ポート 8081で実行します。
webApiA
リソースのアクセス トークンを取得し、Bearer 承認ヘッダーとして http://localhost:8081/webApiA/sample
にアクセスします。
使用法 4: 他のリソース サーバーにアクセスするリソース サーバー
このシナリオは、リソース サーバーにアクセスする
前の手順を参照して、WebApiB
アプリケーションを作成し、アプリケーションのアクセス許可 WebApiB.SampleScope
公開します。
{
"allowedMemberTypes": [
"Application"
],
"description": "WebApiB.SampleScope",
"displayName": "WebApiB.SampleScope",
"id": "04989db0-3efe-4db6-b716-ae378517d2b7",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "WebApiB.SampleScope"
}
WebApiB
アクセス許可に管理者の同意を付与します。
リソース サーバーへのアクセス
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
リソース サーバーへのアクセス シナリオの構成
spring:
cloud:
azure:
active-directory:
b2c:
enabled: true
credential:
client-secret: ${WEB_API_A_AZURE_CLIENT_SECRET}
authorization-clients:
${RESOURCE_SERVER_B_NAME}:
authorization-grant-type: client_credentials
scopes: ${WEB_API_B_APP_ID_URL}/.default
Java コードを記述します。
WebApiA
コントローラー コードについては、次の例を参照してください。
public class SampleController {
/**
* Access to protected data from WebApiA to WebApiB through client credential flow. The access token is obtained by webclient, or
* <p>@RegisteredOAuth2AuthorizedClient("webApiA")</p>. In the end, these two approaches will be executed to
* DefaultOAuth2AuthorizedClientManager#authorize method, get the access token.
*
* @return Respond to protected data from WebApi B.
*/
@GetMapping("/webApiA/webApiB/sample")
@PreAuthorize("hasAuthority('APPROLE_WebApiA.SampleScope')")
public String callWebApiB() {
String body = webClient
.get()
.uri(LOCAL_WEB_API_B_SAMPLE_ENDPOINT)
.attributes(clientRegistrationId("webApiB"))
.retrieve()
.bodyToMono(String.class)
.block();
LOGGER.info("Call callWebApiB(), request '/webApiB/sample' returned: {}", body);
return "Request 'webApiA/webApiB/sample'(WebApi A) returned a " + (body != null ? "success." : "failure.");
}
}
WebApiB
コントローラー コードについては、次の例を参照してください。
public class SampleController {
/**
* webApiB resource api for other web application
* @return test content
*/
@PreAuthorize("hasAuthority('APPROLE_WebApiB.SampleScope')")
@GetMapping("/webApiB/sample")
public String webApiBSample() {
LOGGER.info("Call webApiBSample()");
return "Request '/webApiB/sample'(WebApi B) returned successfully.";
}
}
セキュリティ構成コードは、リソース サーバーへのアクセス シナリオと同じですが、次のように別の Bean webClient
が追加されます。
public class SampleConfiguration {
@Bean
public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction function =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager);
return WebClient.builder()
.apply(function.oauth2Configuration())
.build();
}
}
アプリをビルドしてテストします。 ポート WebApiA
と WebApiB
で と を実行します。
WebApiA
アプリケーションと WebApiB
アプリケーションを起動し、webApiA
リソースのアクセス トークンを取得し、Bearer 承認ヘッダーとして http://localhost:8081/webApiA/webApiB/sample
にアクセスします。
サンプル
詳細については、spring-cloud-azure-starter-active-directory-b2c サンプル