Skip to content

Commit 430d027

Browse files
Add aad b2c resource server sample (Azure#19511)
1 parent 80ff60d commit 430d027

File tree

16 files changed

+222
-11
lines changed

16 files changed

+222
-11
lines changed

sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-b2c-oidc/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Follow the guide of [AAD B2C user flows creation](https://docs.microsoft.com/azu
2929
1. Fill in `${your-tenant-authorization-server-base-uri}` from **Azure AD B2C** portal `App registrations` blade, select **Endpoints**, copy the base endpoint uri(Global cloud format may looks like
3030
`https://{your-tenant-name}.b2clogin.com/{your-tenant-name}.onmicrosoft.com`, China Cloud looks like `https://{your-tenant-name}.b2clogin.cn/{your-tenant-name}.partner.onmschina.cn`).
3131

32-
**NOTE**: The `azure.activedirectory.b2c.tenant` has been deprecated. Please `use azure.activedirectory.b2c.base-uri` instead.
32+
**NOTE**: The `azure.activedirectory.b2c.tenant` has been deprecated. Please use `azure.activedirectory.b2c.base-uri` instead.
3333

3434
2. Select one registered instance under `Applications` from portal, and then:
3535
1. Fill in `${your-client-id}` from `Application ID`.
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Sample for Azure AD B2C Resource server Spring Boot client library for Java
2+
3+
## Key concepts
4+
This sample illustrates how to use `azure-spring-boot-starter-active-directory-b2c` package to work in a resource server and valiate tokens.
5+
6+
1. Constructs trusted iss by configuring tenant id.
7+
2. Obtain the access token from the HTTP request header.
8+
3. Analyze access token to `iss` and construct `JwtDecoder` by `AADIssuerJWSKeySelector`.
9+
4. Use `JwtDecoder` to parse the access token into `Jwt`.
10+
5. Verify `aud`, `iss`, `nbf`, `exp` claims in access token.
11+
12+
## Getting started
13+
### Environment checklist
14+
We need to ensure that this [environment checklist][ready-to-run-checklist] is completed before the run.
15+
16+
### Create and consent Application permissions
17+
1. On the **Azure AD B2C** Portal, select the application that requires roles to be added, select **Manifest**.
18+
2. Find the `appRoles` configuration item, and add the following configuration, then click the **Save** button.
19+
```json
20+
{
21+
"allowedMemberTypes": [
22+
"Application"
23+
],
24+
"description": "Task.read",
25+
"displayName": "Task.read",
26+
"id": "d2bec026-b75f-418d-9493-8462f54f25d9",
27+
"isEnabled": true,
28+
"value": "Test.read"
29+
},
30+
{
31+
"allowedMemberTypes": [
32+
"Application"
33+
],
34+
"description": "Task.wirte",
35+
"displayName": "Task.wirte",
36+
"id": "1ab4eeda-d07e-4bce-8f77-b0a84c97c34f",
37+
"isEnabled": true,
38+
"value": "Test.wirte"
39+
}
40+
```
41+
42+
![Configuration Application Roles](docs/image-configuration-application-roles.png "Configuration Application Roles")
43+
44+
3. Find the application permissions need to use.
45+
46+
![Selected Application](docs/image-selected-application.png "Selected Application")
47+
![Add Application Roles](docs/image-add-application-roles.png "Add Application Roles")
48+
49+
4. Consent Application permissions.
50+
51+
![Consent Application permissions](docs/image-consent-application-permissions.png "Consent Application permissions")
52+
53+
5. In the end, configuration is as follows.
54+
55+
![Final Configuration](docs/image-final-configuration.png "Final Configuration")
56+
57+
## Examples
58+
### Configure the sample
59+
#### application.yml
60+
61+
```yaml
62+
# In v2.0 tokens, `aud` is always the client ID of the API, while in v1.0 tokens it can be the app id uri.
63+
azure:
64+
activedirectory:
65+
b2c:
66+
tenant-id: ${your-tenant-id}
67+
app-id-uri: ${your-app-id-uri} # If you are using v1.0 token, please configure app-id-uri for `aud` verification
68+
client-id: ${your-client-id} # If you are using v2.0 token, please configure client-id for `aud` verification
69+
```
70+
71+
### Run with Maven
72+
```
73+
cd azure-spring-boot-samples/azure-spring-boot-sample-active-directory-b2c-resource-server
74+
mvn spring-boot:run
75+
```
76+
77+
### Access the Web API
78+
We could use Postman to simulate a Web APP to send a request to a Web API.
79+
80+
```http request
81+
GET /write HTTP/1.1
82+
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
83+
```
84+
```http request
85+
GET /read HTTP/1.1
86+
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
87+
```
88+
89+
## Troubleshooting
90+
- `WWW-Authenticate: Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: Read timed out",`
91+
92+
While running sample, if error occurs with logs above:
93+
- `azure-activedirectory-b2c:jwt-read-timeout` to set longer read time in `application.yml`.
94+
95+
### FAQ
96+
#### How do I delete or modify Application Permissions in Portal?
97+
You can set `isEnabled` to `false` in the manifest's JSON configuration.Then delete or modify it.
98+
99+
## Next steps
100+
## Contributing
101+
<!-- LINKS -->
102+
[ready-to-run-checklist]: https://github.com/Azure/azure-sdk-for-java/blob/master/sdk/spring/azure-spring-boot-samples/README.md#ready-to-run-checklist
Loading
Loading
Loading
Loading
Loading
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>org.springframework.boot</groupId>
8+
<artifactId>spring-boot-starter-parent</artifactId>
9+
<version>2.4.0</version> <!-- {x-version-update;org.springframework.boot:spring-boot-starter-parent;external_dependency} -->
10+
</parent>
11+
12+
<groupId>com.azure.spring</groupId>
13+
<artifactId>azure-spring-boot-sample-active-directory-b2c-resource-server</artifactId>
14+
<version>1.0.0</version>
15+
<packaging>jar</packaging>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>com.azure.spring</groupId>
20+
<artifactId>azure-spring-boot-starter-active-directory-b2c</artifactId>
21+
<version>3.3.0-beta.1</version> <!-- {x-version-update;com.azure.spring:azure-spring-boot-starter-active-directory-b2c;current} -->
22+
</dependency>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-web</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
30+
</dependency>
31+
</dependencies>
32+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.spring.sample.aad.b2c;
5+
6+
import org.springframework.boot.SpringApplication;
7+
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
9+
@SpringBootApplication
10+
public class AzureADB2CResourceServerSampleApplication {
11+
12+
public static void main(String[] args) {
13+
SpringApplication.run(AzureADB2CResourceServerSampleApplication.class, args);
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.spring.sample.aad.b2c.controller;
5+
6+
import org.springframework.security.access.prepost.PreAuthorize;
7+
import org.springframework.stereotype.Controller;
8+
import org.springframework.web.bind.annotation.GetMapping;
9+
import org.springframework.web.bind.annotation.ResponseBody;
10+
11+
@Controller
12+
public class WebController {
13+
14+
@ResponseBody
15+
@GetMapping(value = { "/write" })
16+
@PreAuthorize("hasAuthority('APPROLE_Test.write')")
17+
public String write() {
18+
return "Write success.";
19+
}
20+
21+
@ResponseBody
22+
@GetMapping(value = { "/read" })
23+
@PreAuthorize("hasAuthority('APPROLE_Test.read')")
24+
public String read() {
25+
return "Read success.";
26+
}
27+
}

0 commit comments

Comments
 (0)