-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
150 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 7 additions & 1 deletion
8
api-client-spring-boot-starter-sample/src/test/resources/application.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
org.azbuilder.api.url=http://localhost:8080 | ||
org.azbuilder.api.url=http://localhost:8080 | ||
#org.azbuilder.api.clientId=${AzureAdAppClientId} | ||
#org.azbuilder.api.clientSecret=${AzureAdAppClientSecret} | ||
#org.azbuilder.api.tenantId=${AzureAdAppTenantId} | ||
#org.azbuilder.api.scope=${AzureAdAppScope} | ||
|
||
#logging.level.root=INFO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
api-client/src/main/java/org/azbuilder/api/client/security/azure/ClientCredentialApi.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.azbuilder.api.client.security.azure; | ||
|
||
import feign.Headers; | ||
import feign.Param; | ||
import feign.RequestLine; | ||
|
||
import java.util.Map; | ||
|
||
public interface ClientCredentialApi { | ||
|
||
@RequestLine("GET /{tenantId}/oauth2/v2.0/token") | ||
@Headers("Content-Type: application/x-www-form-urlencoded") | ||
Map<String, String> getAccessToken(@Param("tenantId") String tenantId, @Param("grant_type") String grantType, @Param("client_id") String clientId, @Param("scope") String scope, @Param("client_secret") String clientSecret); | ||
} |
86 changes: 86 additions & 0 deletions
86
...src/main/java/org/azbuilder/api/client/security/azure/ClientCredentialAuthentication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.azbuilder.api.client.security.azure; | ||
|
||
import feign.Feign; | ||
import feign.form.FormEncoder; | ||
import feign.gson.GsonDecoder; | ||
import lombok.*; | ||
import lombok.extern.slf4j.Slf4j; | ||
import okhttp3.*; | ||
|
||
import java.io.IOException; | ||
import java.net.HttpURLConnection; | ||
import java.util.Map; | ||
|
||
@Slf4j | ||
public class ClientCredentialAuthentication implements Authenticator, Interceptor { | ||
|
||
private static final String AZURE_ENDPOINT = "https://login.microsoftonline.com"; | ||
private static final String GRANT_TYPE = "client_credentials"; | ||
|
||
private String tenantId; | ||
private String clientId; | ||
private String clientSecret; | ||
private String scope; | ||
private ClientCredentialApi clientCredentialApi; | ||
private String accessToken = ""; | ||
|
||
public ClientCredentialAuthentication(String tenantId, String clientId, String clientSecret, String scope) { | ||
this.tenantId = tenantId; | ||
this.clientId = clientId; | ||
this.clientSecret = clientSecret; | ||
this.scope = scope; | ||
this.clientCredentialApi = Feign.builder() | ||
.encoder(new FormEncoder()) | ||
.decoder(new GsonDecoder()) | ||
.target(ClientCredentialApi.class, AZURE_ENDPOINT); | ||
} | ||
|
||
@Override | ||
public Request authenticate(Route route, Response response) { | ||
log.info("Authentication error {}", response.code()); | ||
synchronized (this) { | ||
this.accessToken = generateAccessToken(); | ||
} | ||
return newRequestWithAccessToken(response.request(), this.accessToken); | ||
} | ||
|
||
@NonNull | ||
private Request newRequestWithAccessToken(@NonNull Request request, String accessToken) { | ||
return request.newBuilder() | ||
.header("Authorization", "Bearer " + accessToken) | ||
.build(); | ||
} | ||
|
||
private String generateAccessToken() { | ||
log.error("Renew Azure Active Directory Token"); | ||
String accessToken = ""; | ||
Map<String, String> response = clientCredentialApi.getAccessToken( | ||
this.tenantId, | ||
GRANT_TYPE, | ||
this.clientId, | ||
this.scope, | ||
this.clientSecret); | ||
|
||
if (response.containsKey("error")) { | ||
throw new RuntimeException(response.get("error_description")); | ||
} | ||
accessToken = response.get("access_token"); | ||
log.info("Successful acquire new Azure AD access token"); | ||
return accessToken; | ||
} | ||
|
||
|
||
@Override | ||
public Response intercept(Chain chain) throws IOException { | ||
Request request = newRequestWithAccessToken(chain.request(), this.accessToken); | ||
Response response = chain.proceed(request); | ||
|
||
if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { | ||
synchronized (this) { | ||
return chain.proceed(newRequestWithAccessToken(request, generateAccessToken())); | ||
} | ||
} | ||
|
||
return response; | ||
} | ||
} |