diff --git a/.run/azure-ad [hpi_run].run.xml b/.run/azure-ad [hpi_run].run.xml
index 347e336a..8259292b 100644
--- a/.run/azure-ad [hpi_run].run.xml
+++ b/.run/azure-ad [hpi_run].run.xml
@@ -12,7 +12,7 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1df7e66a..f30f913b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -157,7 +157,18 @@
com.github.scribejava
scribejava-apis
- 4.2.0
+ 8.3.1
+
+
+
+ com.fasterxml.jackson.datatype
+ *
+
+
+ com.fasterxml.jackson.core
+ *
+
+
org.bitbucket.b_c
diff --git a/src/main/java/com/microsoft/jenkins/azuread/AzureEnvironment.java b/src/main/java/com/microsoft/jenkins/azuread/AzureEnvironment.java
index 537310b3..2781e45d 100644
--- a/src/main/java/com/microsoft/jenkins/azuread/AzureEnvironment.java
+++ b/src/main/java/com/microsoft/jenkins/azuread/AzureEnvironment.java
@@ -20,8 +20,6 @@ static String getAuthorityHost(String azureEnvironmentName) {
switch (azureEnvironmentName) {
case AZURE_CHINA:
return AzureAuthorityHosts.AZURE_CHINA;
- case AZURE_GERMANY:
- return AzureAuthorityHosts.AZURE_GERMANY;
case AZURE_US_GOVERNMENT_L4:
case AZURE_US_GOVERNMENT_L5:
return AzureAuthorityHosts.AZURE_GOVERNMENT;
@@ -35,8 +33,6 @@ static String getGraphResource(String azureEnv) {
switch (azureEnv) {
case AZURE_CHINA:
return "https://microsoftgraph.chinacloudapi.cn/";
- case AZURE_GERMANY:
- return "https://graph.microsoft.de/";
case AZURE_US_GOVERNMENT_L4:
return "https://graph.microsoft.us/";
case AZURE_US_GOVERNMENT_L5:
diff --git a/src/main/java/com/microsoft/jenkins/azuread/AzureSecurityRealm.java b/src/main/java/com/microsoft/jenkins/azuread/AzureSecurityRealm.java
index f9404985..56d54d6d 100644
--- a/src/main/java/com/microsoft/jenkins/azuread/AzureSecurityRealm.java
+++ b/src/main/java/com/microsoft/jenkins/azuread/AzureSecurityRealm.java
@@ -24,8 +24,7 @@
import com.microsoft.graph.options.QueryOption;
import com.microsoft.graph.requests.GraphServiceClient;
import com.microsoft.graph.requests.GroupCollectionPage;
-import com.microsoft.jenkins.azuread.scribe.AzureApi;
-import com.microsoft.jenkins.azuread.scribe.AzureOAuthService;
+import com.microsoft.jenkins.azuread.scribe.AzureAdApi;
import com.microsoft.jenkins.azuread.utils.UUIDValidator;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
@@ -98,7 +97,6 @@
import static com.microsoft.jenkins.azuread.AzureEnvironment.AZURE_US_GOVERNMENT_L4;
import static com.microsoft.jenkins.azuread.AzureEnvironment.AZURE_US_GOVERNMENT_L5;
import static com.microsoft.jenkins.azuread.AzureEnvironment.getAuthorityHost;
-import static com.microsoft.jenkins.azuread.AzureEnvironment.getGraphResource;
import static com.microsoft.jenkins.azuread.AzureEnvironment.getServiceRoot;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
@@ -121,6 +119,7 @@ public class AzureSecurityRealm extends SecurityRealm {
private static final int NOT_FOUND = 404;
private static final int BAD_REQUEST = 400;
public static final String CONVERTER_DISABLE_GRAPH_INTEGRATION = "disableGraphIntegration";
+ public static final String CONVERTER_SINGLE_LOGOUT = "singleLogout";
public static final String CONVERTER_ENVIRONMENT_NAME = "environmentName";
private Cache caches;
@@ -311,15 +310,13 @@ public JwtConsumer getJwtConsumer() {
return jwtConsumer.get();
}
- AzureOAuthService getOAuthService() {
- return (AzureOAuthService) new ServiceBuilder(clientId.getPlainText())
+ OAuth20Service getOAuthService() {
+ return new ServiceBuilder(clientId.getPlainText())
.apiSecret(clientSecret.getPlainText())
.responseType("id_token")
- .scope("openid profile email")
+ .defaultScope("openid profile email")
.callback(getRootUrl() + CALLBACK_URL)
- .build(AzureApi.instance(getGraphResource(getAzureEnvironmentName()),
- this.getTenant(),
- getAuthorityHost(getAzureEnvironmentName())));
+ .build(AzureAdApi.custom(getTenant(), getAuthorityHost(getAzureEnvironmentName())));
}
GraphServiceClient getAzureClient() {
@@ -469,7 +466,7 @@ protected String getPostLogOutUrl2(StaplerRequest req, Authentication auth) {
// Ensure single sign-out
if (singleLogout) {
- return getOAuthService().getLogoutUrl();
+ return ((AzureAdApi) getOAuthService().getApi()).getLogoutUrl();
}
return req.getContextPath() + "/" + AzureAdLogoutAction.POST_LOGOUT_URL;
}
@@ -658,6 +655,10 @@ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingC
writer.startNode(CONVERTER_DISABLE_GRAPH_INTEGRATION);
writer.setValue(String.valueOf(realm.isDisableGraphIntegration()));
writer.endNode();
+
+ writer.startNode(CONVERTER_SINGLE_LOGOUT);
+ writer.setValue(String.valueOf(realm.isSingleLogout()));
+ writer.endNode();
}
@Override
@@ -689,6 +690,9 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co
case CONVERTER_DISABLE_GRAPH_INTEGRATION:
realm.setDisableGraphIntegration(Boolean.parseBoolean(value));
break;
+ case CONVERTER_SINGLE_LOGOUT:
+ realm.setSingleLogout(Boolean.parseBoolean(value));
+ break;
default:
break;
}
diff --git a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureAdApi.java b/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureAdApi.java
new file mode 100644
index 00000000..d32d21bd
--- /dev/null
+++ b/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureAdApi.java
@@ -0,0 +1,34 @@
+package com.microsoft.jenkins.azuread.scribe;
+
+import com.github.scribejava.apis.MicrosoftAzureActiveDirectory20Api;
+
+public class AzureAdApi extends MicrosoftAzureActiveDirectory20Api {
+
+ private final String tenant;
+ private String authorityHost;
+ private static final String OAUTH_2 = "/oauth2";
+
+ AzureAdApi(String tenant, String authorityHost) {
+ super(tenant);
+ this.authorityHost = authorityHost;
+ this.tenant = tenant;
+ }
+
+ public static AzureAdApi custom(String tenant, String authorityHost) {
+ return new AzureAdApi(tenant, authorityHost);
+ }
+
+ @Override
+ public String getAccessTokenEndpoint() {
+ return authorityHost + tenant + OAUTH_2 + getEndpointVersionPath() + "/token";
+ }
+
+ @Override
+ protected String getAuthorizationBaseUrl() {
+ return authorityHost + tenant + OAUTH_2 + getEndpointVersionPath() + "/authorize";
+ }
+
+ public String getLogoutUrl() {
+ return authorityHost + tenant + OAUTH_2 + "/logout";
+ }
+}
diff --git a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureApi.java b/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureApi.java
deleted file mode 100644
index c1c9de8c..00000000
--- a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureApi.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE file in the project root for license information.
- */
-
-package com.microsoft.jenkins.azuread.scribe;
-
-import com.azure.identity.AzureAuthorityHosts;
-import com.github.scribejava.core.extractors.TokenExtractor;
-import com.github.scribejava.core.model.OAuth2AccessToken;
-import com.github.scribejava.core.model.OAuthConfig;
-import com.github.scribejava.core.model.ParameterList;
-import org.apache.commons.lang.StringUtils;
-import com.github.scribejava.core.builder.api.DefaultApi20;
-
-public class AzureApi extends DefaultApi20 {
-
- public static final String DEFAULT_TENANT = "common";
-
- private String tenant;
- private final String loginEndpoint;
-
- private String resource;
-
- protected AzureApi(String resource, String tenant, String loginEndpoint) {
- this.resource = resource;
- this.tenant = tenant;
- this.loginEndpoint = loginEndpoint;
- }
-
- public static AzureApi instance(String resource) {
- return instance(resource, DEFAULT_TENANT, AzureAuthorityHosts.AZURE_PUBLIC_CLOUD);
- }
-
- public static AzureApi instance(String resource, String tenant, String loginEndpoint) {
- return new AzureApi(resource, tenant, loginEndpoint);
- }
-
- private String getBaseEndpoint() {
- StringBuilder url = new StringBuilder();
- url.append(loginEndpoint);
- if (StringUtils.isNotEmpty(tenant)) {
- url.append(tenant);
- } else {
- url.append(DEFAULT_TENANT);
- }
- url.append("/oauth2");
- return url.toString();
- }
-
- @Override
- public String getAccessTokenEndpoint() {
- return getBaseEndpoint() + "/v2.0/token";
- }
- @Override
- protected String getAuthorizationBaseUrl() {
- return getBaseEndpoint() + "/v2.0/authorize";
- }
-
- @Override
- public TokenExtractor getAccessTokenExtractor() {
- return AzureJsonTokenExtractor.instance();
- }
-
- @Override
- public AzureOAuthService createService(OAuthConfig config) {
- return new AzureOAuthService(this, config);
- }
-
- public String getTenant() {
- return tenant;
- }
-
- public String getResource() {
- return resource;
- }
-
- protected String getLogoutBaseUrl() {
- return getBaseEndpoint() + "/logout";
- }
-
- public String getLogoutUrl(String postLogoutUrl) {
- final ParameterList parameters = new ParameterList();
- if (postLogoutUrl != null) {
- parameters.add("post_logout_redirect_uri", postLogoutUrl);
- }
- return parameters.appendTo(getLogoutBaseUrl());
- }
-}
diff --git a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureJsonTokenExtractor.java b/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureJsonTokenExtractor.java
deleted file mode 100644
index 9fc7baac..00000000
--- a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureJsonTokenExtractor.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE file in the project root for license information.
- */
-
-package com.microsoft.jenkins.azuread.scribe;
-
-import com.github.scribejava.core.exceptions.OAuthException;
-import com.github.scribejava.core.extractors.TokenExtractor;
-import com.github.scribejava.core.model.OAuth2AccessToken;
-import com.github.scribejava.core.model.Response;
-import com.github.scribejava.core.utils.Preconditions;
-import com.microsoft.jenkins.azuread.Utils;
-
-import java.io.IOException;
-
-public class AzureJsonTokenExtractor implements TokenExtractor {
-
- private static class InstanceHolder {
- private static final AzureJsonTokenExtractor INSTANCE = new AzureJsonTokenExtractor();
- }
-
- public static AzureJsonTokenExtractor instance() {
- return InstanceHolder.INSTANCE;
- }
-
- protected AzureJsonTokenExtractor() {
- }
-
- @Override
- public OAuth2AccessToken extract(Response response) throws IOException, OAuthException {
- Preconditions.checkEmptyString(response.getBody(),
- "Response body is incorrect. Can't extract a token from an empty string");
- return Utils.JsonUtil.fromJson(response.getBody(), AzureToken.class);
- }
-}
diff --git a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureOAuthService.java b/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureOAuthService.java
deleted file mode 100644
index d57229bf..00000000
--- a/src/main/java/com/microsoft/jenkins/azuread/scribe/AzureOAuthService.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See LICENSE file in the project root for license information.
- */
-
-package com.microsoft.jenkins.azuread.scribe;
-
-import com.github.scribejava.core.model.OAuth2AccessToken;
-import com.github.scribejava.core.model.OAuthConfig;
-import com.github.scribejava.core.model.OAuthConstants;
-import com.github.scribejava.core.model.OAuthRequest;
-import com.github.scribejava.core.oauth.OAuth20Service;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-
-public class AzureOAuthService extends OAuth20Service {
-
- public AzureOAuthService(AzureApi api, OAuthConfig config) {
- super(api, config);
- }
-
- @Override
- protected OAuthRequest createAccessTokenRequest(String code) {
- OAuthRequest request = super.createAccessTokenRequest(code);
- request.addParameter("resource", getApi().getResource());
- return request;
- }
-
- protected OAuthRequest createAccessTokenCredentialGrantRequest() {
- final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), getApi().getAccessTokenEndpoint());
- final OAuthConfig config = getConfig();
- request.addParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
- request.addParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
- request.addParameter(OAuthConstants.SCOPE, config.getScope());
- request.addParameter(OAuthConstants.GRANT_TYPE, "client_credentials");
- return request;
- }
-
- public OAuth2AccessToken getAccessTokenCredentialGrant()
- throws InterruptedException, ExecutionException, IOException {
- final OAuthRequest request = createAccessTokenCredentialGrantRequest();
- return sendAccessTokenRequestSync(request);
- }
-
- @Override
- public AzureApi getApi() {
- return (AzureApi) super.getApi();
- }
-
- public final String getLogoutUrl() {
- return getLogoutUrl(null);
- }
-
- public String getLogoutUrl(String postLogoutUrl) {
- return getApi().getLogoutUrl(postLogoutUrl);
- }
-}
diff --git a/tsconfig.json b/tsconfig.json
index 1cb4ded3..2dd5d087 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,5 +10,6 @@
"allowJs": true,
"resolveJsonModule": true,
"moduleResolution": "node",
- }
+ },
+ "include": ["src/main/frontend/index.ts"],
}