This repo contains two examples using Spring Boot REST API secured with Azure AD OAuth2
Both examples provide libraries and integration to secure REST API (resource server in OAuth 2.0 jargon) with JWT Tokens. In both examples we will use same AzureAD app registrations and tests defined in `tests.http" are using client credentials grant to obtain the token and invoke API.
- Setup Azure API and Client App Registrations
- Microsoft Spring Starter for Azure AD
- Spring Security with Azure AD
- Testing with REST Client
- Testing with Postman
- Setting Scopes for the API
For this example we will simulate two components API Client and API REST Application.
-
API REST Application Registration is used by REST API, resource server for the api will validat that JWT tokens have this app registration as
audience
. [Optional setup] This App registration defines Role exposed by the applications -Admin
for advanced administrative methods. -
API Client Application is used by REST Client and optionally granted role
Admin
to be able to invoke advanced methods, will get 403 if/admin
call ig foles not granted.
Follow the docs to
In our example here is the setup:
-
Create REST API App Registration
MSAADDemoAPI
and define a roleAdmin
exposed by API -
Create Client App Registration
MSAADDemoAPIClient
, create secret and grant it roleAdmin
- [Optionally] Add Role to the user to test Authorization Code Flow. Naviagte to Managed App and add user role
This example is using Microsoft Azure AD Spring Starter that implements all OIDC flows with AzureAD and hides any AAD setup complexity. Microsft Azure AD SpringBoot Starter
This example provides code that is vendor neutral and is using Apringbott Security Module and configuration pointing to OIDC well known config for AAD.
In both examples we will use same AzureAD app registrations and tests defined in `tests.http" are using client credentials grant to obtain the token and invoke API. You will need to install Rest Client extension in VSCode to run it.
- To obtain Azure AD Token via client_credential flow Client Credential Flow and default scope we will use following HTTP request in
tests.http
- Replace values for tenant and app registrations in
tests.http
variables or you could optionally set the Rest Client Environment in vscode settings.json See https://courses.codewithandrea.com/courses/783023/lectures/14364306
POST https://login.microsoftonline.com/{{tenant}}/oauth2/v2.0/token
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id={{appclient_id}}
&client_secret={{appclient_secret}}
&grant_type=client_credentials
&scope={{apiapp_id}}/.default
&request_type=token
Scope is always /.default for client_credentials , it will also be used by AAD to set audience in the token
You could verify content of the token at https://jwt.ms, our decoded token - you will see roles
if granted to client application
{
"aud": "<apiclient_id>",
"iss": "https://sts.windows.net/<tenantid>/",
"iat": 1641967979,
"nbf": 1641967979,
"exp": 1641971879,
"aio": "E2ZgYBCJvVemV+f5aMUG3y6TuQ8YAA==",
"appid": "<appclient_id>",
"appidacr": "1",
"idp": "https://sts.windows.net/<tenantid>/",
"oid": "xxxx",
"rh": "0.AVEA-1rmm50Wt0W8wph-dDYql0aDHVId4mBMs_NAAvwUmBdRAAA.",
"roles": [
"AdminRole"
],
"sub": "xxxx",
"tid": "<tenantid>",
"uti": "vrxcAQO3UUiejUZa1Z6-AQ",
"ver": "1.0"
}
- Run Spring application
mvn spring-boot:run
and test endpoints ( you will receiev 403 in /admin if role not granted )
GET http://localhost:8080/echo
Authorization: Bearer {{getToken.response.body.access_token}}
GET http://localhost:8080/admin
Authorization: Bearer {{getToken.response.body.access_token}}
Postman app allows for easy setup and tests for Authorization Code grant that issues tokens for users - useful for web applications that have authenticated end users and need to obtain token to call Rest API
- Import Postma collection
ADTests.postman_collection.json
that has two flows AuthZ Code Grant and Client Credentials - Setup environment that would define your
appclient_id
,appclient_secret
,apiclient_id
andtenantid
- Verify URLS in Authorization and obtain token
where:
- Authorization URL: https://login.microsoftonline.com/{{tenantid}}/oauth2/authorize
- Token URL: https://login.microsoftonline.com/{{tenantid}}/oauth2/token
- Grant Type: Authorization Code
- ClientID and Secret are set to values for Application Client App Registration
- [Optionally] Scope (see below the setup): api://{{apiclient_id}}/Admin
- Important!! Resource: points to REST API App Registration ID as it will be used in audience
Obtain the token and decode it in jwt.ms
you would see User token
for the currently authenticated user. It will ask for consent to grant if used by user first time.
Refer to https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#payload-claims for more details on token fields.
Token will have aud
set to app registration id for REST API (same as in application.yaml), roles
with Roles associated with User. And optionally scp
set to the requested scope (only avilable in user tokens)
{
"aud": "83ef8978-xxxx <apiclient-id used in resource field>",
"iss": "https://sts.windows.net/<tenantid>/",
"iat": 1642016283,
"nbf": 1642016283,
"exp": 1642020452,
"acr": "1",
"aio": "AXQAi/8TAAAAPUBBoB8/e1hNkutJ2eWul5qq2M+f9Lv+Ws/wo4rtW4BodOpDnuQMiKlajg8muugT/b5D2Oduu42Nflpf+0m+Bv+ZL8N+Bd4T9ueOxOgcf8yLYoFx0QGzuJ6YtXnUPm+nmHXNQa0jXqShRqpBdWQ19g==",
"amr": [
"pwd",
"rsa"
],
"appid": "521d8346-xxxx <appclient-id>",
"appidacr": "1",
"email": "[email protected]",
"idp": "https://sts.windows.net/tenant/",
"ipaddr": "76.78.16.222",
"name": "Elena Neroslavskaya",
"oid": "fc10c12d-xxxxx",
"rh": "0.AVEA-1rmm50Wt0W8wph-dDYql0aDHVId4mBMs_NAAvwUmBdRAMc.",
"roles": [
"AdminRole"
],
"scp": "Admin",
"sub": "CSA-sQ-fxr1i7KPrDVzhpZ1FjPwRuIh_iE7HiUsagUk",
"tid": "tenant",
"unique_name": "[email protected]",
"uti": "-HQQbKuUcESbh02S3vsSAA",
"ver": "1.0"
}
- verify app endpoints
/echo
,/admin
and/adminscope
should work
- Verify settings Authorization and obtain token
where:
- Token URL: https://login.microsoftonline.com/{{tenantid}}/oauth2/token
- Grant Type:Client Credentials
- ClientID and Secret are set to values for Application Client App Registration
- [Optionally] Scope (see below the setup): api://{{apiclient_id}}/.default
- Important!! Resource: points to REST API App Registration ID as it will be used in audience
Obtain the token and decode it in jwt.ms
you would see SP token
for the client application registration.
{
"aud": "83ef8978-xxx <apiclient_id>",
"iss": "https://sts.windows.net/tenant/",
"iat": 1642015217,
"nbf": 1642015217,
"exp": 1642019117,
"aio": "E2ZgYHjp/+BUtt60hJgPy+7lfPtsBgA=",
"appid": "521d8346-<appclient_id>",
"appidacr": "1",
"idp": "https://sts.windows.net/tenant/",
"oid": "7369daa6-3797-xxxx",
"rh": "0.AVEA-1rmm50Wt0W8wph-dDYql0aDHVId4mBMs_NAAvwUmBdRAAA.",
"roles": [
"AdminRole"
],
"sub": "7369daa6-xxxx",
"tid": "tenant",
"uti": "Y8f51RHiZ0ON5klEqOkJAA",
"ver": "1.0"
}
- verify app endpoints
/echo
,/admin
should work (scopes are not available in the client creds tokens)
You could choose to use Scopes vs Roles to do Coarse-Grained Authorization