Open dsyer opened 10 years ago
@dsyer Hi Dave, I recently started using OAuth2 in my app to integrate 3rd party apps like salesforce, google, facebook. I ran through this issue and with lots of research i landed here. The spring security Oauth2 is documented poorly as compared to other spring modules. I always think using spring is too easy because of its thorough documentation, but not in this case. Ok let me present my case. I am using salesforce as provider, i have a pre-established uri with it. When i make use-current-uri to true, salesforce sends me error of redirect-uri mismatch. I now used pre-established URI and handled it with controller. I have written only one line there, to get AccessToken. After provider hits this controler, getting accessToken uses AuthorisationCodeProvider and RestTemplate to use code and state parameter and again redirects to provider again for accessToken. The provider successfully sends accessToken, refreshToken in response and hits back to pre-established-URI.
Can u guide me through how to now redirect to actual client url from this pre-establish-uri which started authorization. One solution i am thinking is saving the current URI in session and then retrieve in pre-established-uri. The drawback for this is that i have to save current uri in all cases which uses protected resources. If this issue has been solved in new version, kindly help me.
@guitarking117 @Nick Williams Do anyone of you find the solution. I am new to implementing Oauth2 and i am facing the similar problem. I am not able to understand if i have to handle the callback URI with controller in my client app, how to implement this controller. There would be two cases in this controller: A- To get access token details if the request contains code parameter and B- To redirect to the client url which actually started oauth2 dance. @dsyer
Does Salesforce really only support redirect to a single URL (most providers allow any URL with a common root)? If so I can see that recovering the original request when the OAuth dance is complete could be challenging. I expect you could leverage Spring Security (since it remembers original requests from before authentication): if you treat the token acquisition as an authentication from the point of view of Spring Security that would be trivial. New Spring Boot (1.3) features set most of it up for you if you declare that you want @EnableOAuth2Sso
, but the pieces are all there in Spring Security OAuth2 (based on OAuth2ClientAuthenticationProcessingFilter
).
@dsyer I cannot move to java configuration as my project is using xml configurations.with 2.5 container. What is the solution?, I am stuck with this for long?
And one more qs. I also use other third party integrations. Do u mean i dont need to handle pre-established-uri with controller. Do i need to use use-current-uri to true always? If so, what is the fun of establishing redirect uri with provider? Why is not to establish then only root of my app.???
I don't think XML will hold you back particularly. You definitely need to register a redirect URL with any sensible provider, it's just that most of them will redirect to anything you ask them to, as long as it starts with the registered value (so paths within your top level resource always work). That's why useCurentUri
defaults to "true" (it works out of the box for most providers).
@dsyer Ok. i registered localhost:7030/oauth/v0/callback as pre-established uri. Will the provider redirect me to url : localhost:7030/oauth/v0/contacts if current-uri set to true?? Or do i need to use localhost:7030/oauth/v0 as pre-establish-uri so that i can use child uri then only as redirects i.e. localhost:7030/oauth/v0/**?
Thanks for ur time and support :) :+1:
It depends on the provider. With most of them you could register localhost:7030
and it would redirect to anything on that host/port. Usually it's a "starts with" pattern. If you register localhost:7030/oauth/v0
that normally means you can only redirect to localhost:7030/oauth/v0/**
.
This still is an issue at least when using Google resources. Google checks agains the full URL and does not use a "starts with" pattern.
Has there been any update on this issue? It's almost 4 years since it was opened and here I am in the future and it's still bothering me :)
So this was a gigantic pain that took me hours and hours of debugging and stepping through, but I finally found a solution. I'll spare everyone the amount of "debug" code I had to write to get to this and just post the solution for anyone else trying to figure this out.
Long story short, when you @EnableOAuth2Sso
, it will return the access token in the SecurityContext
.
Example:
@GetMapping("/hello")
public String helloUser(){
OAuth2AuthenticationDetails authenticationDetails =
(OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails();
String accessToken = authenticationDetails.getTokenValue();
return accessToken;
//or do some call to some ResourceServer with the access token.
}
I sincerely hopes this helps someone out there. I definitely think this could have been better documented. If I missed it some place obvious, hopefully someone will reply to this thread with the link :)
EDIT: For anyone curious, I made a demo project that demonstrates the Authorization Code Grant Flow using three separate projects for Auth Server, Client Web App and Resource API.
@dsyer I am going to revive this thread because I'm facing the same problem. We're trying to access the API of a third-party provider but they only allow one pre-established redirect URL. I'm hoping that support for that will come sooner or later. Thank you very much. :D
After reading SECOAUTH-96 and http://forum.spring.io/forum/spring-projects/security/oauth/118830-pre-established-redirect-uri-in-oauth-resource about 10 times and scouring the code, I'm convinced there's a huge disconnect here, and that this feature is NOT complete.
Here's a very simple use case that should be easily satisfied:
This seems pretty simple and standard, but is not possible with Spring Security OAuth 1.0.5. SECOAUTH-96 described this use case, and so by marking it complete I would think that means the use case is supported. But it is not.
The first thing I did was get it working with the "current" URL instead of a pre-registered URL, to confirm nothing else was getting in the way. If I accessed /clientApp/foo and got redirected to the authorization server, the authorization server ultimately send me back to /clientApp/foo with the authorization code and state parameters. This worked great, and I was able to access protected resources after authorizing. (One big problem, though, is that the user is never redirected again after being returned to /clientApp/foo, so they land on a page where they can see the code and state parameters in their browser URL. That's a no-no.)
So then I set use-current-uri to false and pre-established-redirect-uri to http://myserver.com/clientApp/oauth/confirm and tried things again. The user is correctly redirected to the authorization server with http://myserver.com/clientApp/oauth/confirm as the redirect URL parameter. After authorizing, the authorization server correctly redirects the user to http://myserver.com/clientApp/oauth/confirm with the code and state parameters. However, at this point the client application returns a 404. I assumed there was some filter somewhere that intercepted the request because it works for "current" URLs, but after scouring the source code I can't actually find any code that intercepts requests to retrieve these parameters and exchange them for the access token. It's like magic, except that it doesn't work for a static, pre-registered URL.
Thinking that I needed a controller to at least back the request, I added a controller to match the http://myserver.com/clientApp/oauth/confirm URL. Now I don't get a 404 anymore, but the parameters are still never detected and exchanged for an access token. If I attempt to go back to the client URL that needed an access token to begin with, I simply get sent back to the authorization server to start all over again.
In essence, once I start using pre-established-redirect-uri, Spring Security OAuth 2 (for the client-side anyway) just stops working completely. This makes it essentially useless for clients with multiple URLs that access protected resources on a provider that permits only one, pre-registered redirect URI.
Maybe (hopefully) I'm missing something. But I spent a day reading documentation and looking at sample applications (and there are no samples that use pre-established redirect URIs), a week trying to get this to work, and a further two days just reading the source code. I can't get it to work and I don't know how it could possibly work based on what I've seen.
Comments:
david_syer on Sat, 5 Oct 2013 12:30:03 +0100
guitarking117 on Sun, 6 Oct 2013 15:46:10 +0100
guitarking117 on Sun, 6 Oct 2013 15:54:16 +0100
guitarking117 on Sun, 6 Oct 2013 16:08:52 +0100
david_syer on Mon, 7 Oct 2013 19:18:44 +0100
guitarking117 on Mon, 7 Oct 2013 19:49:23 +0100
guitarking117 on Tue, 8 Oct 2013 06:36:23 +0100