3
votes

This is my configuration for OAuth2 login with Instagram

instagram:
  client:
    clientId: clientId
    clientSecret: clientSeret
    accessTokenUri: https://api.instagram.com/oauth/access_token
    userAuthorizationUri: https://api.instagram.com/oauth/authorize
    clientAuthenticationScheme: form
  scope:
    - basic
    - public_content
  resource:
    userInfoUri: https://api.instagram.com/v1/users/self/
    delimiter: +

This is the request made by Spring:

https://api.instagram.com/oauth/authorize?client_id=clientId&redirect_uri=http://localhost:8080/login/instagram&response_type=code&state=CG6mMQ

How can I change the response_type to &response_type=token and how can I why isn't Spring adding the scopes?

Here is the App class:

@SpringBootApplication
@EnableOAuth2Client
public class App extends WebSecurityConfigurerAdapter {

    @Autowired
    OAuth2ClientContext oauth2ClientContext;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(App.class, args);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/login**", "/webjars/**")
                .permitAll()
                .anyRequest()
                .authenticated().and().exceptionHandling()
                .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
                // logout
                .and().logout().logoutSuccessUrl("/").permitAll()
                // CSRF
                .and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                // filters
                .and().addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
    }

    private Filter ssoFilter() {
        CompositeFilter filter = new CompositeFilter();
        List<Filter> filters = new ArrayList<>();

        // facebook ...
        // google ...

        // instagram
        OAuth2ClientAuthenticationProcessingFilter instagramFilter =
                new OAuth2ClientAuthenticationProcessingFilter("/login/instagram");
        OAuth2RestTemplate instagramTemplate =
                new OAuth2RestTemplate(instagram(), oauth2ClientContext);
        instagramFilter.setRestTemplate(instagramTemplate);
        instagramFilter.setTokenServices(
                new UserInfoTokenServices(instagramResource().getUserInfoUri(), instagram().getClientId()));
        filters.add(instagramFilter);

        filter.setFilters(filters);
        return filter;
    }

    @Bean
    @ConfigurationProperties("instagram.client")
    public AuthorizationCodeResourceDetails instagram() {
        return new AuthorizationCodeResourceDetails();
    }

    @Bean
    @ConfigurationProperties("instagram.resource")
    public ResourceServerProperties instagramResource() {
        return new ResourceServerProperties();
    }

    @Bean
    public FilterRegistrationBean oauth2ClientFilterRegistration(
            OAuth2ClientContextFilter filter) {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(filter);
        registration.setOrder(-100);
        return registration;
    }
}
2

2 Answers

1
votes

How can I change the response_type to &response_type=token

As I read the code, AuthorizationCodeAccessTokenProvider‘s response_type is hard code.

private UserRedirectRequiredException getRedirectForAuthorization(AuthorizationCodeResourceDetails resource,
            AccessTokenRequest request) {

        // we don't have an authorization code yet. So first get that.
        TreeMap<String, String> requestParameters = new TreeMap<String, String>();
        requestParameters.put("response_type", "code"); // oauth2 spec, section 3

So, If you want to change the response_code, you can extend the AuthorizationCodeAccessTokenProvider, or implements the AccessTokenProvider, and then inject to the OAuth2RestTemplate accessTokenProvider(the default value is a AccessTokenProviderChain that contains AuthorizationCodeAccessTokenProvider, ResourceOwnerPasswordAccessTokenProvider and so on, use your own provider instead of AuthorizationCodeAccessTokenProvider).

Or you can change the redirectStrategy in OAuth2ClientContextFilter, and change the request param when redirect, but I don't recommend this.

How can I why isn't Spring adding the scopes?

AuthorizationCodeAccessTokenProvider will get scopes from AuthorizationCodeResourceDetails, and add them to UserRedirectRequiredException. I think the scope can't be injected to AuthorizationCodeResourceDetails, because the scope is not under the client. Maybe you need to change to this.

instagram:
  client:
    clientId: clientId
    clientSecret: clientSeret
    accessTokenUri: https://api.instagram.com/oauth/access_token
    userAuthorizationUri: https://api.instagram.com/oauth/authorize
    clientAuthenticationScheme: form
    scope:
      - basic
      - public_content
0
votes

You can access the query parameters from the UserRedirectRequiredException. So in the code which throws the exception and thus causes the redirect to happen, e.g. in your filter, you can do something like:

try {
    accessToken = restTemplate.getAccessToken();
}
catch (UserRedirectRequiredException e) {
    Map<String, String> requestParams = e.getRequestParams();
    requestParams.put("response_type", "token");

    throw e; //don't forget to rethrow
}

You can only replace values this way. If you needed to add a parameter value alongside an existing value, you'd need to use a delimiter such as '+'. There is no standard way of adding multiple parameter values and would depend on what the owner of the API accepts. Some APIs may not accept delimeters at all.