IDP - Azure AD Implementation¶
Implement identity-provider operations for Microsoft Entra ID/Azure AD and B2C.
Configure tenant/client credentials and the selected provider mode. Match the authority/scopes and user/group permissions to the actual directory operations used by the application.
| Maven artifact | Packaging | Source project |
|---|---|---|
org.fireflyframework:fireflyframework-security-idp-azure-ad |
jar |
modules/security-idp-azure-ad |
Part of Security and identity.
In the onboarding service¶
Connect applicant or reviewer identity operations to the configured Entra ID or Azure AD B2C tenant. Select the supported mode and client configuration separately from the onboarding application data.
Add the component¶
Installation and version availability explains source builds and published releases.
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-security-idp-azure-ad</artifactId>
<version>26.10.20-SNAPSHOT</version>
</dependency>
Quick start¶
The injection examples use Lombok @RequiredArgsConstructor. Add its provided dependency and annotation processor as described in Constructor injection.
The Java examples in this section are API fragments for application code. Use the stated imports and supply the application-owned collaborators described alongside them.
- Add the dependency (above) and select the provider:
firefly:
security:
idp:
provider: azure-ad # selects this adapter
azure-ad:
mode: entra-id # "entra-id" (default) or "b2c"
tenant-id: ${AZURE_TENANT_ID}
client-id: ${AZURE_CLIENT_ID}
client-secret: ${AZURE_CLIENT_SECRET}
That is all the wiring needed. AzureAdAutoConfiguration registers an IdpAdapter bean automatically.
- Inject the
IdpAdapterand use it. Your code depends only on the framework SPI, never on Azure AD types, so it stays portable across providers:
import lombok.RequiredArgsConstructor;
import org.fireflyframework.security.idp.adapter.IdpAdapter;
import org.fireflyframework.security.idp.dtos.*;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
@RequiredArgsConstructor
public class AuthFacade {
private final IdpAdapter idp;
public Mono<ResponseEntity<TokenResponse>> login(String username, String password) {
return idp.login(LoginRequest.builder()
.username(username)
.password(password)
.build());
}
public Mono<ResponseEntity<UserInfoResponse>> me(String accessToken) {
return idp.getUserInfo(accessToken);
}
public Mono<ResponseEntity<CreateUserResponse>> register(CreateUserRequest request) {
return idp.createUser(request);
}
}
Configuration and wiring¶
The firefly.security.idp.azure-ad namespace is bound by AzureAdProperties.java. Nested configuration is declared in the linked class. Defaults are the field initializers.
| Setting | Java type | Source default |
|---|---|---|
firefly.security.idp.azure-ad.mode |
String |
"entra-id" |
firefly.security.idp.azure-ad.tenant-id |
String |
not initialized |
firefly.security.idp.azure-ad.client-id |
String |
not initialized |
firefly.security.idp.azure-ad.client-secret |
String |
not initialized |
firefly.security.idp.azure-ad.b2c |
B2CProperties |
new B2CProperties() |
firefly.security.idp.azure-ad.role-mapping |
RoleMappingProperties |
new RoleMappingProperties() |
firefly.security.idp.azure-ad.connection-timeout |
Integer |
30000 |
firefly.security.idp.azure-ad.request-timeout |
Integer |
60000 |
firefly.security.idp.azure-ad.graph |
GraphProperties |
new GraphProperties() |
Property-based wiring conditions found in this module:
name = "firefly.security.idp.provider", havingValue = "azure-ad". AzureAdAutoConfiguration.java.name = "firefly.security.idp.azure-ad.mode", havingValue = "entra-id", matchIfMissing = true. AzureAdAutoConfiguration.java.name = "firefly.security.idp.azure-ad.mode", havingValue = "b2c". AzureAdAutoConfiguration.java.
Public API and extension points¶
| Type | Contract and responsibility |
|---|---|
AzureAdIdpAdapter |
Azure AD implementation of the Firefly IDP Adapter. |
AzureAdProperties |
Carries mode, tenantId, clientId, clientSecret, b2c data; field constraints and defaults are declared in the linked source. |
AzureAdAdminService |
Admin service interface for Azure AD user management operations. |
GraphClientFactory |
Defines createClient, destroy operations. |
MsalClientFactory |
Defines createClient, destroy operations. |
Related components¶
| Related component | Why it belongs nearby |
|---|---|
| Identity Provider | Define identity-provider contracts and common authentication/user/group management services. |
Build and test¶
Use Java 25. From the repository root, build this component with its required dependencies:
git clone https://github.com/fireflyframework/fireflyframework-jafly.git
cd fireflyframework-jafly
./mvnw -pl :fireflyframework-security-idp-azure-ad -am verify
./mvnw -pl :fireflyframework-security-idp-azure-ad -am install
verify runs the selected projects' tests. install makes the current build available in your local Maven repository.
Representative test sources:
Mock, local-container, and application-context tests do not establish acceptance against a live provider account. Validate the intended provider deployment and credentials separately.
Test fixture¶
The testChangePassword_Success test demonstrates one concrete behavior. Excerpt from AzureAdIdpAdapterTest.java. The test class supplies its fixtures and imports.
@Test
void testChangePassword_Success() {
// Arrange
ChangePasswordRequest request = ChangePasswordRequest.builder()
.userId("testuser")
.oldPassword("oldpass")
.newPassword("newpass")
.build();
when(adminService.changePassword(any(ChangePasswordRequest.class)))
.thenReturn(Mono.empty());
// Act & Assert
StepVerifier.create(adapter.changePassword(request))
.verifyComplete();
verify(adminService).changePassword(request);
}
Detailed reference¶
Configuration¶
All properties live under the firefly.security.idp.azure-ad prefix and map to AzureAdProperties.
firefly.security.idp.provider=azure-ad (defined by the IDP core) is what activates this adapter.
firefly:
security:
idp:
provider: azure-ad # required: selects the Azure AD adapter
azure-ad:
mode: entra-id # "entra-id" (default) or "b2c"
tenant-id: your-tenant-id # required
client-id: your-client-id # required
client-secret: your-client-secret # required
connection-timeout: 30000 # MSAL HTTP connect timeout (ms)
request-timeout: 60000 # MSAL HTTP read timeout (ms)
role-mapping:
strategy: app-roles # "app-roles" (default), "groups", or "both"
group-prefix: "" # only map groups whose name starts with this prefix
graph:
scopes: # Microsoft Graph token scopes
- https://graph.microsoft.com/.default
b2c: # only used when mode = b2c
domain: your-tenant.b2clogin.com
sign-up-sign-in-policy: B2C_1_signup_signin
reset-password-policy: B2C_1_password_reset
Key properties¶
| Property | Default | Description |
|---|---|---|
firefly.security.idp.provider |
(none) | Must be azure-ad to activate this adapter (defined by the IDP core). |
firefly.security.idp.azure-ad.mode |
entra-id |
Selects the admin strategy: entra-id or b2c. |
firefly.security.idp.azure-ad.tenant-id |
(required) | Azure AD / Entra tenant ID. |
firefly.security.idp.azure-ad.client-id |
(required) | App-registration client ID. |
firefly.security.idp.azure-ad.client-secret |
(required) | App-registration client secret. |
firefly.security.idp.azure-ad.connection-timeout |
30000 |
MSAL4J HTTP connect timeout in milliseconds. |
firefly.security.idp.azure-ad.request-timeout |
60000 |
MSAL4J HTTP read timeout in milliseconds. |
firefly.security.idp.azure-ad.role-mapping.strategy |
app-roles |
How roles are derived: app-roles, groups, or both. |
firefly.security.idp.azure-ad.role-mapping.group-prefix |
"" |
Only security groups with this name prefix are mapped to roles. |
firefly.security.idp.azure-ad.graph.scopes |
https://graph.microsoft.com/.default |
OAuth2 scopes used when acquiring Graph tokens. |
firefly.security.idp.azure-ad.b2c.domain |
(none) | B2C login domain (e.g. tenant.b2clogin.com); drives the authority URL in B2C mode. |
firefly.security.idp.azure-ad.b2c.sign-up-sign-in-policy |
B2C_1_signup_signin |
B2C sign-up/sign-in user-flow name. |
firefly.security.idp.azure-ad.b2c.reset-password-policy |
B2C_1_password_reset |
B2C password-reset user-flow name. |
tenant-id, client-id, and client-secret are validated with @NotBlank. The application fails fast
at startup if any is missing. The effective MSAL authority is derived automatically:
https://login.microsoftonline.com/{tenant-id} for Entra ID, or
https://{b2c.domain}/{tenant-id} for B2C.
How It Works¶
AzureAdAutoConfiguration.@ConditionalOnProperty(firefly.security.idp.provider=azure-ad)and@ConditionalOnClass(ConfidentialClientApplication.class); registers the client factories, services, and theIdpAdapterbean. The admin-service bean is chosen byfirefly.security.idp.azure-ad.mode.AzureAdIdpAdapter. implementsIdpAdapter; delegates auth/token calls toAzureAdAuthServiceand admin calls to the selectedAzureAdAdminService.AzureAdAuthService. login (ROPC), refresh, logout, introspect, user info, and token revocation via MSAL4J + Graph.EntraIdAdminService/B2CAdminService. user, role, session, and password operations via the Microsoft Graph SDK;B2CAdminService extends EntraIdAdminServicewith B2C local-account overrides.MsalClientFactory/GraphClientFactory. lazily build and cache the confidential-client and Graph clients, released on shutdown.AzureAdTokenParser. local, dependency-free JWT decoding for introspection and user-ID extraction.
Continue the application¶
Use the Identity Provider guide for the next part of this integration. The runnable submission/query service is in Getting started.