Enabling OAuth1 Support on a Jersey Jax-rs web service

后端 未结 1 1818
一生所求
一生所求 2021-01-05 22:44

I\'d like to enable OAuth1 Provider support on my restful web service. Jersey supports this as described here Jersey OAuth1 Provider support. I\'ve been trying to register

相关标签:
1条回答
  • 2021-01-05 23:01

    I realise this thread is somewhat old - but having just got it work myself, I felt a reply was in order! Given time, I may even create a blog post with a fuller example. Be warned - this is not a short answer!

    There is an absolute lack of examples on information on using the OAuth1 server (aka Provider) feature in Jersey - I can't remember a tech topic that revealed so little useful Google information. I almost passed on looking for another solution since it led me to think perhaps it didn't work. But, with some perseverance, I can say that not only is it usable, but it seems to work rather well. Plus of course, if you're already using Jersey for your REST API - you don't need any extra libs.

    I am not an OAuth1 expert - and I'd strongly recommend some background reading for those attempting this. I am also assuming here you have Jersey working, understand things like ContainerRequestFilters, and also have some internal means to authorize users.

    My examples also use the excellent JAX-RS OSGi connector - the only real difference is that where we use an OSGi bundle context to register the OAuth1 feature via an OSGI service, regular Jersey users will need to configure via their normal Application / Server config model.

    Initialisation

    You must create your OAuth1 feature - and give it a provider:

    DefaultOAuth1Provider oap = new DefaultOAuth1Provider();
    Feature oaFeature = new OAuth1ServerFeature(oap, "oauth1/request_token", "oauth1/access_token");       
    

    Don't forget to register oaFeature into Jersey!

    The DefaultOAuth1Provider is entirely memory based - which was fine for us to start with. Many will want to persist access tokens for use across server restarts, which will require an extended subclass (or clean implementation)

    Add in your Consumers Keys and Secrets

    It took me a while to realise Consumers were not users but clients i.e. applications. The Jersey implementation will not work if you don't register keys and secrets for each consumer (aka client app) that wishes to connect

    oap.registerConsumer("some-owner-id", 
                          "abcdef" ,
                          "123456",
                          new MultivaluedHashMap<String,String> ());
    

    You obviously would never hard-code these, and further would use some form of secure store for the secret (param 3).

    If you do not add these you will not get any further.

    OAuth protocol step 1 - get a request token

    At this stage you are ready client side to get a request token - and here there is a perfectly good example on GitHub.

    ConsumerCredentials consumerCredentials = new ConsumerCredentials("abcdef","123456");
    
    //TODO - user proper client builder with real location + any ssl context
    OAuth1AuthorizationFlow authFlow = OAuth1ClientSupport.builder(consumerCredentials)
                .authorizationFlow(
                        "http://myhost:8080/myapi/oauth1/request_token",
                        "http://myhost:8080/myapi/oauth1/access_token",
                        "http://myhost:8080/myapi/oauth1/authorize")
                .build();
    String authorizationUri = authFlow.start();
    System.out.println("Auth URI: " + authorizationUri); 
    

    Obviously you would change URLs to point to your server and - crucially - the client needs to use the same Conumer Key and Secret you registered in the server.

    You will get back a response with an oauth_token string in it e.g.

    http://myhost:8080/myapi/oauth/authorize?oauth_token=a1ec37598da
    b47f6b9d770b1b23a5f99
    

    OAuth protocol step 2 - authorize the user

    As you will read in any article, actual user Authorization is outside of the scope of OAuth1 - at this stage you must invoke your servers auth process whatever that is.

    However!!!! What is not outside the OAuth1 scope is what your server needs to do if the user authorizes successfully. You must tell your DefaultOAuth1Provider about the successful auth:

    // Dummy code - make out like we're auth'd
    Set<String> dummyRoles = new HashSet<> (Arrays.asList( new String[] { "my-role-1", "my-role-2" }));
    DefaultOAuth1Provider.Token tok1 = getRequestToken("a1ec37598da
    b47f6b9d770b1b23a5f99");
    String verifier = authorizeToken(tok1, new Principal()
                {
                    public String getName()
                    {
                        return "my-user";
                    }
                }, 
                dummyRoles);
    System.out.println("***** verifier: " + verifier);
    

    Note the request token string is that from step 1. Obviously a real implementation would pass a real Principal and set of roles for the authorized user.

    Also, of course, printing out the verifier is not much use - you need to get that back to your client in some way, either via an independent channel or possibly as a header in the auth response - which maybe would need to be encrypted for added protection.

    OAuth protocol step 3 - swap the request token for an access token

    Once the client receives or has the verifier entered manually, it can finalize the process and swap the request token for an access token e.g.

    String verifier = System.console().readLine("%s", "Verifier: ");
    final AccessToken accessToken = authFlow.finish(verifier);        
    System.out.println("Access token: " + accessToken.getToken());      
    

    Again, not a realistic example - but it shows the process.

    If your OAuth1Provider saves access tokens to some persistent store on the server, you can re-use any access token returned here on a future session without going through all the previous steps.

    That's it - you then just need to make sure every request the client creates from this point on in the process makes use of that access token.

    0 讨论(0)
提交回复
热议问题