diff --git a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties index faf3f874661..1050ecb88d2 100644 --- a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties +++ b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties @@ -110,22 +110,25 @@ che.auth.access_denied_error_page=/error-oauth che.auth.reserved_user_names= # Configuration of the Azure DevOps Service OAuth2 client. Used to obtain personal access tokens. -# Location of the file with Azure DevOps Service Application ID. +# Location of the file with Microsoft OIDC Directory (tenant) ID. +che.oauth2.azure.devops.tenantid_filepath=NULL + +# Location of the file with Microsoft OIDC Application (client) ID. che.oauth2.azure.devops.clientid_filepath=NULL -# Location of the file with Azure DevOps Service Client Secret. +# Location of the file with Microsoft OIDC Application (client) secret. che.oauth2.azure.devops.clientsecret_filepath=NULL # Azure DevOps Service OAuth2 scopes. # Separate multiple values with comma, for example: scope,scope,scope # The full list of scopes: https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops#scopes -che.integration.azure.devops.application_scopes=vso.code_write +che.integration.azure.devops.application_scopes=499b84ac-1321-427f-aa17-267ca6975798/vso.code_write -# Azure DevOps Service OAuth2 authorization URI. -che.oauth.azure.devops.authuri=https://app.vssps.visualstudio.com/oauth2/authorize +# Azure DevOps Service OAuth2 authorization URI template. Tenant-id must be injected. +che.oauth.azure.devops.authuri.template=https://login.microsoftonline.com/%s/oauth2/v2.0/authorize -# Azure DevOps OAuth Service token URI. -che.oauth.azure.devops.tokenuri=https://app.vssps.visualstudio.com/oauth2/token +# Azure DevOps OAuth Service token URI template. Tenant-id must be injected. +che.oauth.azure.devops.tokenuri.template=https://login.microsoftonline.com/%s/oauth2/v2.0/token # Azure DevOps Service API server address. che.integration.azure.devops.api_endpoint=https://vssps.dev.azure.com diff --git a/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticator.java b/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticator.java index cde28785aba..22814782961 100644 --- a/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticator.java +++ b/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2024 Red Hat, Inc. + * Copyright (c) 2012-2026 Red Hat, Inc. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -22,6 +22,7 @@ import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl; import com.google.api.client.auth.oauth2.AuthorizationCodeTokenRequest; import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.auth.oauth2.TokenResponse; import com.google.api.client.util.store.MemoryDataStoreFactory; import com.google.common.io.CharStreams; import java.io.IOException; @@ -29,6 +30,7 @@ import java.io.InputStreamReader; import java.net.URI; import java.net.URL; +import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; @@ -51,6 +53,7 @@ public class AzureDevOpsOAuthAuthenticator extends OAuthAuthenticator { private final String[] redirectUris; private final String API_VERSION = "7.0"; private final String PROVIDER_NAME = "azure-devops"; + private final String clientId; private final String clientSecret; private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @@ -66,6 +69,7 @@ public AzureDevOpsOAuthAuthenticator( String[] redirectUris) throws IOException { this.cheApiEndpoint = cheApiEndpoint; + this.clientId = clientId; this.clientSecret = clientSecret; this.azureDevOpsScmApiEndpoint = trimEnd(azureDevOpsScmApiEndpoint, '/'); this.azureDevOpsUserProfileDataApiUrl = @@ -87,7 +91,7 @@ public AzureDevOpsOAuthAuthenticator( @Override public String getAuthenticateUrl(URL requestUrl, List scopes) { AuthorizationCodeRequestUrl url = flow.newAuthorizationUrl().setScopes(scopes); - url.set("response_type", "Assertion"); + url.set("response_type", "code"); url.set("redirect_uri", format("%s/oauth/callback", cheApiEndpoint)); url.setState(prepareState(requestUrl)); return url.build(); @@ -200,11 +204,10 @@ protected AuthorizationCodeTokenRequest getAuthorizationCodeTokenRequest( URL requestUrl, List scopes, String code) { AuthorizationCodeTokenRequest request = super.getAuthorizationCodeTokenRequest(requestUrl, scopes, code); - request.set("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"); - request.set("assertion", code); - request.set("client_assertion", clientSecret); - request.set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); - request.setResponseClass(AzureDevOpsTokenResponse.class); + request.set("client_id", clientId); + request.set("grant_type", "authorization_code"); + request.set("client_secret", URLEncoder.encode(clientSecret)); + request.setResponseClass(TokenResponse.class); return request; } } diff --git a/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticatorProvider.java b/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticatorProvider.java index f6af12de857..38db1c0e8ba 100644 --- a/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticatorProvider.java +++ b/wsmaster/che-core-api-auth-azure-devops/src/main/java/org/eclipse/che/security/oauth/AzureDevOpsOAuthAuthenticatorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2023 Red Hat, Inc. + * Copyright (c) 2012-2026 Red Hat, Inc. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ @@ -38,18 +38,20 @@ public class AzureDevOpsOAuthAuthenticatorProvider implements Providerhttps://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops#response---authorize-app - * - * @author Anatolii Bazko - */ -public class AzureDevOpsTokenResponse extends TokenResponse { - @JsonString - @Key("expires_in") - private Long expiresInSeconds; - - public Long getExpiresInSeconds() { - return expiresInSeconds; - } - - public AzureDevOpsTokenResponse setExpiresInSeconds(Long expiresInSeconds) { - this.expiresInSeconds = expiresInSeconds; - return this; - } -}