-
Notifications
You must be signed in to change notification settings - Fork 137
/
InteractiveRequest.java
123 lines (98 loc) · 5.29 KB
/
InteractiveRequest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.microsoft.aad.msal4j;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.Accessors;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
@Accessors(fluent = true)
class InteractiveRequest extends MsalRequest {
@Getter(AccessLevel.PACKAGE)
private AtomicReference<CompletableFuture<IAuthenticationResult>> futureReference;
@Getter(AccessLevel.PACKAGE)
private InteractiveRequestParameters interactiveRequestParameters;
@Getter(AccessLevel.PACKAGE)
private String verifier;
@Getter(AccessLevel.PACKAGE)
private String state;
private PublicClientApplication publicClientApplication;
private URL authorizationUrl;
InteractiveRequest(InteractiveRequestParameters parameters,
AtomicReference<CompletableFuture<IAuthenticationResult>> futureReference,
PublicClientApplication publicClientApplication,
RequestContext requestContext) {
super(publicClientApplication, null, requestContext);
this.interactiveRequestParameters = parameters;
this.futureReference = futureReference;
this.publicClientApplication = publicClientApplication;
validateRedirectUrl(parameters.redirectUri());
}
URL authorizationUrl() {
if (this.authorizationUrl == null) {
authorizationUrl = createAuthorizationUrl();
}
return authorizationUrl;
}
private void validateRedirectUrl(URI redirectUri) {
String host = redirectUri.getHost();
String scheme = redirectUri.getScheme();
InetAddress address;
//Validate URI scheme. Only http is valid, as determined by the HttpListener created in AcquireTokenByInteractiveFlowSupplier.startHttpListener()
if (scheme == null || !scheme.equals("http")) {
throw new MsalClientException(String.format(
"Only http://localhost or http://localhost:port is supported for the redirect URI of an interactive request using a browser, but \"%s\" was found. For more information about redirect URI formats, see https://aka.ms/msal4j-interactive-request", scheme),
AuthenticationErrorCode.LOOPBACK_REDIRECT_URI);
}
//Ensure that the given redirect URI has a known address
try {
address = InetAddress.getByName(host);
} catch (UnknownHostException e) {
throw new MsalClientException(String.format(
"Unknown host exception for host \"%s\". For more information about redirect URI formats, see https://aka.ms/msal4j-interactive-request", host),
AuthenticationErrorCode.LOOPBACK_REDIRECT_URI);
}
//Ensure that the redirect URI is considered a loopback address
if (address == null || !address.isLoopbackAddress()) {
throw new MsalClientException(
"Only loopback redirect URI is supported for interactive requests. For more information about redirect URI formats, see https://aka.ms/msal4j-interactive-request",
AuthenticationErrorCode.LOOPBACK_REDIRECT_URI);
}
}
private URL createAuthorizationUrl() {
AuthorizationRequestUrlParameters.Builder authorizationRequestUrlBuilder =
AuthorizationRequestUrlParameters
.builder(interactiveRequestParameters.redirectUri().toString(),
interactiveRequestParameters.scopes())
.prompt(interactiveRequestParameters.prompt())
.claimsChallenge(interactiveRequestParameters.claimsChallenge())
.loginHint(interactiveRequestParameters.loginHint())
.domainHint(interactiveRequestParameters.domainHint())
.correlationId(publicClientApplication.correlationId())
.instanceAware(interactiveRequestParameters.instanceAware())
.extraQueryParameters(interactiveRequestParameters.extraQueryParameters());
addPkceAndState(authorizationRequestUrlBuilder);
AuthorizationRequestUrlParameters authorizationRequestUrlParameters =
authorizationRequestUrlBuilder.build();
return publicClientApplication.getAuthorizationRequestUrl(
authorizationRequestUrlParameters);
}
private void addPkceAndState(AuthorizationRequestUrlParameters.Builder builder) {
// Create code verifier and code challenge as described in https://tools.ietf.org/html/rfc7636
SecureRandom secureRandom = new SecureRandom();
byte[] randomBytes = new byte[32];
secureRandom.nextBytes(randomBytes);
verifier = Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes);
state = UUID.randomUUID().toString() + UUID.randomUUID().toString();
builder.codeChallenge(StringHelper.createBase64EncodedSha256Hash(verifier))
.codeChallengeMethod("S256")
.state(state);
}
}