Skip to content

Commit

Permalink
Add support for generic authorities
Browse files Browse the repository at this point in the history
  • Loading branch information
Avery-Dunn committed Aug 6, 2024
1 parent c1ca9ff commit 9ca1559
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,25 @@ void acquireTokenClientCredentials_ClientSecret_Ciam() throws Exception {
assertNotNull(result.accessToken());
}

@Test
void acquireTokenClientCredentials_Certificate_CiamCud() throws Exception {
String authorityCud = "https://login.msidlabsciam.com/fe362aec-5d43-45d1-b730-9755e60dc3b9/v2.0/";
String clientId = "b244c86f-ed88-45bf-abda-6b37aa482c79";

ConfidentialClientApplication cca = ConfidentialClientApplication.builder(
clientId, CertificateHelper.getClientCertificate())
.oidcAuthority(authorityCud)
.build();

IAuthenticationResult result = cca.acquireToken(ClientCredentialParameters
.builder(Collections.singleton(TestConstants.DEFAULT_SCOPE))
.build())
.get();

assertNotNull(result);
assertNotNull(result.accessToken());
}

@Test
void acquireTokenClientCredentials_Callback() throws Exception {
String clientId = TestConstants.MSIDLAB_CLIENT_ID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void runSeleniumAutomatedLogin(User user, AbstractClientApplicationBase app) {
SeleniumExtensions.performADOrCiamLogin(seleniumDriver, user);
} else if (authorityType == AuthorityType.ADFS) {
SeleniumExtensions.performADFS2019Login(seleniumDriver, user);
} else if (authorityType == AuthorityType.CIAM) {
} else if (authorityType == AuthorityType.CIAM || authorityType == AuthorityType.GENERIC) {
SeleniumExtensions.performADOrCiamLogin(seleniumDriver, user);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,24 @@ public T b2cAuthority(String val) throws MalformedURLException {
return self();
}

/**
* Set a known authority corresponding to a generic OpenIdConnect Identity Provider.
* MSAL will append ".well-known/openid-configuration" to the authority to retrieve the OIDC metadata and determine the endpoints.
*
* @param val a string value of authority
* @return instance of the Builder on which method was called
*/
public T oidcAuthority(String val) throws MalformedURLException {
authority = Authority.enforceTrailingSlash(val);
URL authorityURL = new URL(authority);

authenticationAuthority = new GenericAuthority(authorityURL);

Authority.validateAuthority(authenticationAuthority.canonicalAuthorityUrl());

return self();
}

/**
* Set a boolean value telling the application if the authority needs to be verified
* against a list of known authorities. Authority is only validated when:
Expand Down
11 changes: 6 additions & 5 deletions msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/Authority.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
/**
* Represents Authentication Authority responsible for issuing access tokens.
*/

@Accessors(fluent = true)
@Getter(AccessLevel.PACKAGE)
abstract class Authority {
Expand Down Expand Up @@ -63,8 +62,10 @@ static Authority createAuthority(URL authorityUrl) throws MalformedURLException{
createdAuthority = new B2CAuthority(authorityUrl);
} else if (authorityType == AuthorityType.ADFS) {
createdAuthority = new ADFSAuthority(authorityUrl);
} else if(authorityType == AuthorityType.CIAM){
} else if (authorityType == AuthorityType.CIAM) {
createdAuthority = new CIAMAuthority(authorityUrl);
} else if (authorityType == AuthorityType.GENERIC) {
createdAuthority = new GenericAuthority(authorityUrl);
} else {
throw new IllegalArgumentException("Unsupported Authority Type");
}
Expand All @@ -79,11 +80,11 @@ static AuthorityType detectAuthorityType(URL authorityUrl) {

final String path = authorityUrl.getPath().substring(1);
if (StringHelper.isBlank(path)) {
if(isCiamAuthority(authorityUrl.getHost())){
if (isCiamAuthority(authorityUrl.getHost())) {
return AuthorityType.CIAM;
} else {
return AuthorityType.GENERIC;
}
throw new IllegalArgumentException(
"authority Uri should have at least one segment in the path (i.e. https://<host>/<path>/...)");
}

final String host = authorityUrl.getHost();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
package com.microsoft.aad.msal4j;

enum AuthorityType {
AAD, ADFS, B2C, CIAM
AAD, ADFS, B2C, CIAM, GENERIC
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import java.net.MalformedURLException;
import java.net.URL;

public class CIAMAuthority extends Authority{
public class CIAMAuthority extends Authority {

public static final String CIAM_HOST_SEGMENT = ".ciamlogin.com";

Expand All @@ -23,20 +23,22 @@ public class CIAMAuthority extends Authority{
CIAMAuthority(URL authorityUrl) throws MalformedURLException {
super(transformAuthority(authorityUrl), AuthorityType.CIAM);
setAuthorityProperties();
this.authority = String.format(CIAM_AUTHORITY_FORMAT,host,tenant);
this.authority = String.format(CIAM_AUTHORITY_FORMAT, host, tenant);
}

/** This method takes a CIAM authority string of format "tenant.ciamlogin.com" or "https://tenant.ciamlogin.com"
and converts it into a full authority url with a path segment of format "/tenant.onmicrosoft.com"
/**
* This method takes a CIAM authority string of format "tenant.ciamlogin.com" or "https://tenant.ciamlogin.com"
* and converts it into a full authority url with a path segment of format "/tenant.onmicrosoft.com"
*
* @param originalAuthority authority to be transformed
* @return full CIAM authority with path
*/
protected static URL transformAuthority(URL originalAuthority) throws MalformedURLException {
String host = originalAuthority.getHost() + originalAuthority.getPath();
String transformedAuthority = originalAuthority.toString();
if(originalAuthority.getPath().equals("/")){
if (originalAuthority.getPath().equals("/")) {
int ciamHostIndex = host.indexOf(CIAMAuthority.CIAM_HOST_SEGMENT);
String tenant = host.substring(0 , ciamHostIndex);
String tenant = host.substring(0, ciamHostIndex);
transformedAuthority = originalAuthority + tenant + ".onmicrosoft.com/";
}
return new URL(transformedAuthority);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.aad.msal4j;

import java.net.MalformedURLException;
import java.net.URL;

public class GenericAuthority extends Authority {
static final String AUTHORIZATION_ENDPOINT = "oauth2/v2.0/authorize";
static final String TOKEN_ENDPOINT = "oauth2/v2.0/token";
static final String DEVICE_CODE_ENDPOINT = "oauth2/v2.0/devicecode";

//Part of the OpenIdConnect standard, this is appended to the authority to create the endpoint that has OIDC metadata
static final String WELL_KNOWN_OPENID_CONFIGURATION = ".well-known/openid-configuration";

private static final String AUTHORITY_FORMAT = "https://%s/%s/";
private static final String DEVICE_CODE_ENDPOINT_FORMAT = AUTHORITY_FORMAT + DEVICE_CODE_ENDPOINT;
private static final String AUTHORIZATION_ENDPOINT_FORMAT = AUTHORITY_FORMAT + AUTHORIZATION_ENDPOINT;
private static final String TOKEN_ENDPOINT_FORMAT = AUTHORITY_FORMAT + TOKEN_ENDPOINT;

GenericAuthority(URL authorityUrl) throws MalformedURLException {
super(transformAuthority(authorityUrl), AuthorityType.GENERIC);

setAuthorityProperties();
this.authority = String.format(AUTHORITY_FORMAT, host, tenant);
}

private static URL transformAuthority(URL originalAuthority) throws MalformedURLException {
String transformedAuthority = originalAuthority.toString();
transformedAuthority += WELL_KNOWN_OPENID_CONFIGURATION;

return new URL(transformedAuthority);
}

private void setAuthorityProperties() {
this.authorizationEndpoint = String.format(AUTHORIZATION_ENDPOINT_FORMAT, host, tenant);
this.tokenEndpoint = String.format(TOKEN_ENDPOINT_FORMAT, host, tenant);
this.deviceCodeEndpoint = String.format(DEVICE_CODE_ENDPOINT_FORMAT, host, tenant);
this.selfSignedJwtAudience = this.tokenEndpoint;
}
}

0 comments on commit 9ca1559

Please sign in to comment.