Skip to content

Add a new provider: Aad #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions simple/src/main/java/com/example/AadAccessTokenProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
import org.springframework.security.oauth2.common.OAuth2AccessToken;

/**
* Created by bmill on 3/22/2016.
*/
public class AadAccessTokenProvider extends AuthorizationCodeAccessTokenProvider

{
@Override
public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request) throws UserRedirectRequiredException, UserApprovalRequiredException, AccessDeniedException, OAuth2AccessDeniedException {
return super.obtainAccessToken(details, request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.security.oauth2.client.DefaultOAuth2RequestAuthenticator;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.web.client.RestTemplate;

public class AadOauth2RequestAuthenticator extends DefaultOAuth2RequestAuthenticator {

@Autowired
private RestTemplate restTemplate;

@Override
public void authenticate(OAuth2ProtectedResourceDetails resource,
OAuth2ClientContext clientContext,
ClientHttpRequest request)
{
// this call is too late. the token call was already made
super.authenticate(resource, clientContext, request);
}

class AccessRequest {
private final String client_id;
private final String client_secret;
private final String code;
private final String grant_type;
private final String redirect_uri;
private final String resource;

public AccessRequest(String client_id, String client_secret, String code, String grant_type, String redirect_uri, String resource) {
this.client_id = client_id;
this.client_secret = client_secret;
this.code = code;
this.grant_type = grant_type;
this.redirect_uri = redirect_uri;
this.resource = resource;
}


public String getClient_id() {
return client_id;
}

public String getClient_secret() {
return client_secret;
}

public String getCode() {
return code;
}

public String getGrant_type() {
return grant_type;
}

public String getRedirect_uri() {
return redirect_uri;
}

public String getResource() {
return resource;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example;

import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateCustomizer;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;

import java.io.IOException;
import java.util.Arrays;

public class AadUserInfoRestTemplateCustomizer implements UserInfoRestTemplateCustomizer {
@Override
public void customize(OAuth2RestTemplate oAuth2RestTemplate) {

// no help here
// by the time the authenticator is called, the token has already been retrieved
oAuth2RestTemplate.setAuthenticator(new AadOauth2RequestAuthenticator());

// Attempt 1: Use my own token provider, but it never gets called...
oAuth2RestTemplate.setAccessTokenProvider(new AadAccessTokenProvider());

// Even better, if only OAuth2RestTemplate provided a getter for AccessTokenProvider, I could add interceptors and or enhancers
//AuthorizationCodeAccessTokenProvider provider = oAuth2RestTemplate.getAccessTokenProvider();

ClientHttpRequestInterceptor myInterceptor = new ClientHttpRequestInterceptor() {
@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {

ClientHttpResponse response = clientHttpRequestExecution.execute(httpRequest, bytes);
return response;

}
};

oAuth2RestTemplate.setInterceptors(Arrays.asList(myInterceptor));
}
}
23 changes: 23 additions & 0 deletions simple/src/main/java/com/example/AzureRequestEnhancer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.example;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.RequestEnhancer;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

@Component
public class AzureRequestEnhancer implements RequestEnhancer {
@Value("${aad.resource:null}")
private String aadResource;

@Override
public void enhance(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, MultiValueMap<String, String> form, HttpHeaders headers) {
if (!StringUtils.isEmpty(resource)) {
form.set("resource", aadResource);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.RequestEnhancer;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;

@Component
public class AzureRequestEnhancerCustomizer {
@Autowired
private OAuth2RestTemplate userInfoRestTemplate;

@Autowired
private AzureRequestEnhancer azureRequestEnhancer;

@PostConstruct
public void testWiring() {
AuthorizationCodeAccessTokenProvider authorizationCodeAccessTokenProvider = new AuthorizationCodeAccessTokenProvider();
authorizationCodeAccessTokenProvider.setTokenRequestEnhancer(azureRequestEnhancer);
userInfoRestTemplate.setAccessTokenProvider(authorizationCodeAccessTokenProvider);
}
}


6 changes: 6 additions & 0 deletions simple/src/main/java/com/example/SocialApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateCustomizer;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableOAuth2Sso
Expand All @@ -27,4 +29,8 @@ public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}

@Bean
public UserInfoRestTemplateCustomizer aadUserInfoRestTemplate() {
return new AadUserInfoRestTemplateCustomizer();
}
}
21 changes: 13 additions & 8 deletions simple/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
aad:
resource: https://graph.windows.net

security:
oauth2:
client:
clientId: 233668646673605
clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
accessTokenUri: https://graph.facebook.com/oauth/access_token
userAuthorizationUri: https://www.facebook.com/dialog/oauth
tokenName: oauth_token
authenticationScheme: query
clientId: [clientid]
clientSecret: [clientsecret]
accessTokenUri: https://login.microsoftonline.com/[tenant-id]/oauth2/token
userAuthorizationUri: https://login.microsoftonline.com/[tenant-id]/oauth2/authorize
clientAuthenticationScheme: form
scope: openid
resource:
userInfoUri: https://graph.facebook.com/me
userInfoUri: https://graph.windows.net/me?api-version=1.6
spring:
resources:
chain:
enabled: true


logging:
level:
org.springframework.security: DEBUG