spring-attic / spring-security-oauth

Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
http://github.com/spring-projects/spring-security-oauth
Apache License 2.0
4.69k stars 4.05k forks source link

Using spring-security as an OAuth client to access dropbox api's fail #412

Closed shahamit closed 3 years ago

shahamit commented 9 years ago

I am trying to use dropbox's api (https://www.dropbox.com/developers/core/docs)with OAuth authorization but unable to successful make the call. Below code fails with a NPE.


    private String authorizeWithImplicitFlow() {
        ImplicitResourceDetails details = new ImplicitResourceDetails();
        details.setClientId(CLIENT_ID);
        details.setPreEstablishedRedirectUri("https://www.irctc.co.in");
        details.setUserAuthorizationUri("https://www.dropbox.com/1/oauth2/authorizeWithImplicitFlow");

        OAuth2RestTemplate template = new OAuth2RestTemplate(details);
        OAuth2AccessToken token = template.getAccessToken();
        return token.getValue();
    }

The error trace is

Exception in thread "main" java.lang.NullPointerException
    at java.lang.StringBuilder.<init>(StringBuilder.java:112)
    at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.getAccessTokenUri(OAuth2AccessTokenSupport.java:162)
    at org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:137)
    at org.springframework.security.oauth2.client.token.grant.implicit.ImplicitAccessTokenProvider.obtainAccessToken(ImplicitAccessTokenProvider.java:61)
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142)
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
    at com.oauth.dropbox.SpringDropboxApp.authorizeWithImplicitFlow(SpringDropboxApp.java:35)
    at com.oauth.dropbox.SpringDropboxApp.accessAccount(SpringDropboxApp.java:24)
    at com.oauth.dropbox.SpringDropboxApp.executeNonStatic(SpringDropboxApp.java:20)
    at com.oauth.dropbox.SpringDropboxApp.main(SpringDropboxApp.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

The above code might not be the right but I didn't find any sample code that I could follow. Apart from the errors I have a couple of questions while I tried the above code

  1. What jars should be included in the classpath for an oauth2 client? Currently I have spring-core-4.1.4.RELEASE.jar, spring-security-core-3.2.5.RELEASE.jar, spring-security-oauth2-2.0.6.RELEASE.jar, spring-web-4.1.4.RELEASE.jar & commons-logging-1.1.1.jar. Since the library versions are not of the same version, I would like to get suggestions on what should be the correct library set?
  2. How can I pass custom parameters? Dropbox API (or any other api provider for that case) exposes different custom parameters to be passed while making the authorize or the token end point call. For e.g. access response_type or state or force_reapprove etc. in case of the dropbox token endpoint. How do I pass custom parameters while making the authorization api calls?

It would be helpful to get a link to the sample code that can be referred.

Thanks!

dsyer commented 9 years ago

You have to set the "accessTokenUri" not the "userAuthorizationUri" for the implicit resource type (makes sense since that's where you get the token from I guess). That will fix the NPE.

How can I pass custom parameters?

Use an AccessTokenRequest in your OAuth2RestTemplate (create it with the other constructor).

What jars should be included in the classpath for an oauth2 client?

Those look fine. I would recommend using the Spring IO platform if you want something comprehensive. But you can also just depend on security-oauth2 and take the transitive dependencies that it provides.

shahamit commented 9 years ago

Thanks for the reply. It partly helped me in resolving the NPE but I get a 403 (Forbidden) "access_denied" error. org.springframework.web.client.RestTemplate handleResponseError WARNING: POST request for "https://www.dropbox.com/1/oauth2/authorize" resulted in 403 (Forbidden); invoking error handler Exception in thread "main" error="access_denied", error_description="Error requesting access token." My current code is

    private String authorizeWithImplicitFlow() {
        ImplicitResourceDetails details = new ImplicitResourceDetails();
        details.setPreEstablishedRedirectUri("https://www.irctc.co.in");
        details.setAccessTokenUri("https://www.dropbox.com/1/oauth2/authorize");

        HashMap<String, String[]> parameters = new HashMap<String, String[]>();
        parameters.put("response_type", new String[] {"token"});
        parameters.put("client_id", new String[]{CLIENT_ID});
        OAuth2RestTemplate template = new OAuth2RestTemplate(details, new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest(parameters)));
        OAuth2AccessToken token = template.getAccessToken();
        return token.getValue();
    }
dsyer commented 9 years ago

How do you expect the request to be authenticated? It seems like Dropbox is just telling you there's a problem with your authentication.

shahamit commented 9 years ago

I expected the token to be granted. I tried the same request through a rest client (PostMan) and it worked.

I realized that the spring security oauth client is making a POST request, how do I mark it as a GET request? That could be the cause of the issue.

I thought enabling debug/trace logs for "org.springframework.security.oauth2" but that didn't help.

dsyer commented 9 years ago

You didn't answer the question: "How do you expect the request to be authenticated?" How do you tell Dropbox your username and password (for instance)?

P.S. you don't have to set the client_id or the response_type in the request (the token provider does that for you).

shahamit commented 9 years ago

I understand your question. I missed this point while making the code work. I am writing an java application that will make calls to the dropbox api's.

Is there a way to block the java application through a prompt until the user authorizes the client application for making api calls? The access token returned by the authorization server can then be entered by the user (who ran the java application) on the command prompt.

This should be a one time activity since the access tokens returned by dropbox api's effectively never expire.

dsyer commented 9 years ago

Is there a way to block the java application through a prompt

You mean like System.in.read()?

You don't need your own OAuth2ClientContext if you are accepting a token through your UI. Just grab the token and put it in the context that comes with the OAuth2RestTemplate.

jgrandja commented 3 years ago

Closing this as questions are better suited on Stack Overflow. We prefer to use GitHub issues for bugs and enhancements.