Skip to content

Commit f99994d

Browse files
committed
First draft agent ID support
1 parent ebf788b commit f99994d

10 files changed

Lines changed: 1139 additions & 0 deletions

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractApplicationBase.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ private AuthenticationResultSupplier getAuthenticationResultSupplier(MsalRequest
115115
supplier = new AcquireTokenByUserFederatedIdentityCredentialSupplier(
116116
(ConfidentialClientApplication) this,
117117
(UserFederatedIdentityCredentialRequest) msalRequest);
118+
} else if (msalRequest instanceof AcquireTokenForAgentRequest) {
119+
supplier = new AcquireTokenForAgentSupplier(
120+
(ConfidentialClientApplication) this,
121+
(AcquireTokenForAgentRequest) msalRequest);
118122
} else if (msalRequest instanceof ManagedIdentityRequest) {
119123
supplier = new AcquireTokenByManagedIdentitySupplier(
120124
(ManagedIdentityApplication) this,
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.aad.msal4j;
5+
6+
import java.util.Map;
7+
import java.util.Set;
8+
9+
import static com.microsoft.aad.msal4j.ParameterValidationUtils.validateNotNull;
10+
11+
/**
12+
* Object containing parameters for the composite agent token acquisition flow.
13+
* This orchestrates the full three-leg FMI/FIC token exchange: the developer passes
14+
* scopes and an {@link AgentIdentity}, and MSAL handles Legs 1-3 internally.
15+
* <p>
16+
* Can be used as parameter to
17+
* {@link ConfidentialClientApplication#acquireTokenForAgent(AcquireTokenForAgentParameters)}
18+
*/
19+
public class AcquireTokenForAgentParameters implements IAcquireTokenParameters {
20+
21+
private Set<String> scopes;
22+
private AgentIdentity agentIdentity;
23+
private boolean forceRefresh;
24+
private ClaimsRequest claims;
25+
private Map<String, String> extraHttpHeaders;
26+
private Map<String, String> extraQueryParameters;
27+
private String tenant;
28+
29+
private AcquireTokenForAgentParameters(
30+
Set<String> scopes,
31+
AgentIdentity agentIdentity,
32+
boolean forceRefresh,
33+
ClaimsRequest claims,
34+
Map<String, String> extraHttpHeaders,
35+
Map<String, String> extraQueryParameters,
36+
String tenant) {
37+
this.scopes = scopes;
38+
this.agentIdentity = agentIdentity;
39+
this.forceRefresh = forceRefresh;
40+
this.claims = claims;
41+
this.extraHttpHeaders = extraHttpHeaders;
42+
this.extraQueryParameters = extraQueryParameters;
43+
this.tenant = tenant;
44+
}
45+
46+
/**
47+
* Builder for {@link AcquireTokenForAgentParameters}.
48+
*
49+
* @param scopes scopes application is requesting access to
50+
* @param agentIdentity the identity of the agent and (optionally) the target user
51+
* @return builder that can be used to construct AcquireTokenForAgentParameters
52+
*/
53+
public static AcquireTokenForAgentParametersBuilder builder(
54+
Set<String> scopes, AgentIdentity agentIdentity) {
55+
validateNotNull("scopes", scopes);
56+
validateNotNull("agentIdentity", agentIdentity);
57+
58+
return new AcquireTokenForAgentParametersBuilder()
59+
.scopes(scopes)
60+
.agentIdentity(agentIdentity);
61+
}
62+
63+
public Set<String> scopes() {
64+
return this.scopes;
65+
}
66+
67+
public AgentIdentity agentIdentity() {
68+
return this.agentIdentity;
69+
}
70+
71+
public boolean forceRefresh() {
72+
return this.forceRefresh;
73+
}
74+
75+
public ClaimsRequest claims() {
76+
return this.claims;
77+
}
78+
79+
public Map<String, String> extraHttpHeaders() {
80+
return this.extraHttpHeaders;
81+
}
82+
83+
public Map<String, String> extraQueryParameters() {
84+
return this.extraQueryParameters;
85+
}
86+
87+
public String tenant() {
88+
return this.tenant;
89+
}
90+
91+
public static class AcquireTokenForAgentParametersBuilder {
92+
private Set<String> scopes;
93+
private AgentIdentity agentIdentity;
94+
private boolean forceRefresh;
95+
private ClaimsRequest claims;
96+
private Map<String, String> extraHttpHeaders;
97+
private Map<String, String> extraQueryParameters;
98+
private String tenant;
99+
100+
AcquireTokenForAgentParametersBuilder() {
101+
}
102+
103+
AcquireTokenForAgentParametersBuilder scopes(Set<String> scopes) {
104+
this.scopes = scopes;
105+
return this;
106+
}
107+
108+
AcquireTokenForAgentParametersBuilder agentIdentity(AgentIdentity agentIdentity) {
109+
this.agentIdentity = agentIdentity;
110+
return this;
111+
}
112+
113+
/**
114+
* If true, the request will ignore cached access tokens on read, but will still write
115+
* them to the cache once obtained from the identity provider. The default is false.
116+
*
117+
* @param forceRefresh whether to bypass the user token cache
118+
* @return this builder
119+
*/
120+
public AcquireTokenForAgentParametersBuilder forceRefresh(boolean forceRefresh) {
121+
this.forceRefresh = forceRefresh;
122+
return this;
123+
}
124+
125+
/**
126+
* Claims to be requested through the OIDC claims request parameter, allowing requests
127+
* for standard and custom claims.
128+
*
129+
* @param claims {@link ClaimsRequest}
130+
* @return this builder
131+
*/
132+
public AcquireTokenForAgentParametersBuilder claims(ClaimsRequest claims) {
133+
this.claims = claims;
134+
return this;
135+
}
136+
137+
/**
138+
* Adds additional headers to the token request.
139+
*
140+
* @param extraHttpHeaders headers to include
141+
* @return this builder
142+
*/
143+
public AcquireTokenForAgentParametersBuilder extraHttpHeaders(Map<String, String> extraHttpHeaders) {
144+
this.extraHttpHeaders = extraHttpHeaders;
145+
return this;
146+
}
147+
148+
/**
149+
* Adds additional query parameters to the token request.
150+
*
151+
* @param extraQueryParameters query parameters to include
152+
* @return this builder
153+
*/
154+
public AcquireTokenForAgentParametersBuilder extraQueryParameters(Map<String, String> extraQueryParameters) {
155+
this.extraQueryParameters = extraQueryParameters;
156+
return this;
157+
}
158+
159+
/**
160+
* Sets the tenant for the request, overriding the application's configured authority.
161+
*
162+
* @param tenant tenant ID or domain
163+
* @return this builder
164+
*/
165+
public AcquireTokenForAgentParametersBuilder tenant(String tenant) {
166+
this.tenant = tenant;
167+
return this;
168+
}
169+
170+
public AcquireTokenForAgentParameters build() {
171+
return new AcquireTokenForAgentParameters(
172+
scopes, agentIdentity, forceRefresh, claims,
173+
extraHttpHeaders, extraQueryParameters, tenant);
174+
}
175+
}
176+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.aad.msal4j;
5+
6+
/**
7+
* Internal request class for the composite agent token acquisition flow.
8+
* This request does not create its own grant; actual grants are produced
9+
* by the inner CCA calls orchestrated by {@link AcquireTokenForAgentSupplier}.
10+
*/
11+
class AcquireTokenForAgentRequest extends MsalRequest {
12+
13+
AcquireTokenForAgentParameters parameters;
14+
15+
AcquireTokenForAgentRequest(AcquireTokenForAgentParameters parameters,
16+
ConfidentialClientApplication application,
17+
RequestContext requestContext) {
18+
super(application, null, requestContext);
19+
this.parameters = parameters;
20+
}
21+
}

0 commit comments

Comments
 (0)