🍃
Spring BootでAzure Active DirectoryのOAuth2認証を利用する
Spring Boot にて、Azure Active DirectoryのOAuth2認証を利用してみます。
Azure Active Directory用の Spring Boot Starterが用意されているので簡単に実装することができます。
今回確認に利用したプロジェクト全体は、下記に配置しています。
Azure Active Directory側での準備
Azure Active Directory側で下記を用意しておく必要があります。
- (テナントが未作成なら)テナント作成
- 「アプリの登録」から、
- 「新規登録」で、対象のアプリケーションを登録
- リダイレクトURIは
http://localhost:8080/login/oauth2/code/
に
- リダイレクトURIは
- 「証明書とシークレット」で、新しいクライアントシークレットを作成
- 「アプリロール」からアプリロールの作成
- 「新規登録」で、対象のアプリケーションを登録
- (ユーザが未作成なら)ユーザの作成
- 「エンタープライズ アプリケーション」で登録したアプリケーションを選び、「ユーザとグループ」から「ユーザまたはグループの追加」を選んで、ユーザ+ロールの組み合わせを割り当て
詳しい操作は下記が参考になります。
プロジェクト
Spring Bootの最新(2022年10月23日時点)となる2.7.5で確認します。
- Java 17
- Spring Boot 2.7.5
- Gradle 7.5
build.gradle
は下記のようになります。
build.gradle
plugins {
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
}
group = 'com.github.onozaty'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
ext {
set('springCloudAzureVersion', "4.3.0") // 4.4.0 だと問題があって動かないため
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.azure.spring:spring-cloud-azure-starter-active-directory'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "com.azure.spring:spring-cloud-azure-dependencies:${springCloudAzureVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
spring-cloud-azure-starter
の最新は4.4.0ですが、4.4.0では下記の問題があって、OAuth2でエラーが発生します。1つ前の4.3.0だと問題が無いので、4.3.0を使って回避しています。
Azure Active Directoryの情報をアプリケーション側に設定
Active Directoryの情報を設定します。以下は例です。
src/main/resources/application.properties
# Enable related features.
spring.cloud.azure.active-directory.enabled=true
# Specifies your Active Directory ID:
spring.cloud.azure.active-directory.profile.tenant-id=22222222-2222-2222-2222-222222222222
# Specifies your App Registration's Application ID:
spring.cloud.azure.active-directory.credential.client-id=11111111-1111-1111-1111-1111111111111111
# Specifies your App Registration's secret key:
spring.cloud.azure.active-directory.credential.client-secret=AbCdEfGhIjKlMnOpQrStUvWxYz==
簡単なWebページの作成
アクセスの制御を確認するため、下記の3つのHTMLを作成します。
-
src/main/resources/static/index.html
トップページ -
src/main/resources/static/admin/admin.html
admin向けのページ -
src/main/resources/static/user/user.html
user向けのページ
src/main/resources/static/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Top</title>
</head>
<body>
<ul>
<li><a href="./admin/admin.html">Admin</a></li>
<li><a href="./user/user.html">User</a></li>
<li><a href="./logout">Logout</a></li>
</ul>
</body>
</html>
src/main/resources/static/admin/admin.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Admin</title>
</head>
<body>
<ul>
<li><a href="../">Top</a></li>
<li><a href="../user/user.html">User</a></li>
<li><a href="../logout">Logout</a></li>
</ul>
</body>
</html>
src/main/resources/static/user/user.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>User</title>
</head>
<body>
<ul>
<li><a href="../">Top</a></li>
<li><a href="../admin/admin.html">Admin</a></li>
<li><a href="../logout">Logout</a></li>
</ul>
</body>
</html>
Spring Security の設定
ロール毎にアクセス先の制限を行うため、独自のセキュリティ構成を設定します。
src/main/java/com/example/azure/AzureAdOAuthLoginSecurityConfig.java
package com.example.azure;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.azure.spring.cloud.autoconfigure.aad.AadWebSecurityConfigurerAdapter;
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AzureAdOAuthLoginSecurityConfig extends AadWebSecurityConfigurerAdapter {
// https://learn.microsoft.com/ja-jp/azure/developer/java/spring-framework/spring-boot-starter-for-azure-active-directory-developer-guide#protect-a-resource-serverapi
// 独自のセキュリティ構成にしたい場合は、AadWebSecurityConfigurerAdapterを継承して指定する
// (デフォルトはDefaultAadResourceServerWebSecurityConfigurerAdapterで構成したものになっている)
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
// https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html
http.authorizeHttpRequests(
authz -> authz
// admin配下は要adminロール(アプリロールで指定した名前がAPPROLE_の後に付く)
.mvcMatchers("/admin/**").hasAnyAuthority("APPROLE_admin")
// user配下は要userロール
.mvcMatchers("/user/**").hasAnyAuthority("APPROLE_user")
// それ以外のリクエストも全て認証必要(ロールは何でもOK(無くてもOK))
.anyRequest().authenticated());
http.logout(
// GETでもログアウトが受け付けられるように
logout -> logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout")));
}
}
動作確認
アプリロールでadminとuserの両方が割り当てられているユーザでログインします。
権限があるのでAdminのページも問題無く表示されます。
アプリロールでuserのみが割り当てられているユーザでログインします。
Adminのページに遷移すると、権限が無いので 403 Forbidden となります。
Discussion