These are chat archives for spring-cloud/spring-cloud

18th
Jan 2017
Bryan Perino
@bryantp
Jan 18 2017 04:41
Hi All. Has anyone used Spring Cloud with UAA's Identity Zones?
I am having an issue where I am trying to authenticate a user in a zone, but the url for UAA has to be specific to the zone.
and it keeps going to whatever I have defined in my application.yml file
Dave Syer
@dsyer
Jan 18 2017 07:34
How does your app know the zone?
Dieter Hubau
@Turbots
Jan 18 2017 07:46
@pcornelissen you cannot change the port while the server is running; you will need to stop the server, change the property (in properties files, environment variable or as argument) and restart
Patrick Cornelißen
@pcornelissen
Jan 18 2017 07:55
that’s what I thought too, but avanish realized that already
Bryan Perino
@bryantp
Jan 18 2017 14:24
@dsyer That's a good question. In that point in the OAuth flow, I don't think we know anything about the user other than their login credentials.
Dave Syer
@dsyer
Jan 18 2017 14:40
Then you can't really expect to know where to send the request. Does the user know what zone he wants to log into?
Normally if there is a choice of authentication sources, the user chooses (e.g. twitter or github)
I don't think this is really a spring-cloud concern though (unless we uncover a hidden requirement somehow)
Bryan Perino
@bryantp
Jan 18 2017 14:42
I figured it was more specific to UAA than Spring Cloud. I was just being hopeful that there was some hidden setting for this to work.
Although, I don't see a way it could with the way it works now
Dave Syer
@dsyer
Jan 18 2017 14:43
I don't see a way it could full stop.
Bryan Perino
@bryantp
Jan 18 2017 14:43
The only way I know which zone they are in is when I do a lookup in my database.
Dave Syer
@dsyer
Jan 18 2017 14:44
Sounds like the answer is in your hands. How did that data get into your database?
Bryan Perino
@bryantp
Jan 18 2017 14:44
When the user signs up, we store their tenant's subdomain.
Dave Syer
@dsyer
Jan 18 2017 14:45
How did they sign up without knowing the subdomain?
There's a chicken and egg problem.
Bryan Perino
@bryantp
Jan 18 2017 14:45
Well, I only have new user sign up now
users to an existing identity zone would have to get an email to join, which is a feature of UAA
New users create the identity zone when they are created
Dave Syer
@dsyer
Jan 18 2017 14:47
If you have a mapping from userid to subdomain then you can construct a redirect URL I guess.
But I don't really have a clear picture of where that would come from (the mapping).
Bryan Perino
@bryantp
Jan 18 2017 14:49
I will try to explain better.
When a user wants to register with my application, they are asked what they would like to name their Org (Identity Zone). This registration is available to all on our website, just a normal website sign up form.
I then go and create the Identity Zone in UAA with a REST call, create the user in UAA with another call, and then save a local "shadow" copy on my application.
This shadow copy keeps track of the remote user's UUID and their Identity Zone.
This is what I would use to lookup a user's Identity Zone
Dave Syer
@dsyer
Jan 18 2017 14:51
Right, so you can construct a mapping from userid -> UAA subdomain
Bryan Perino
@bryantp
Jan 18 2017 14:51
Correct
Dave Syer
@dsyer
Jan 18 2017 14:51
And from that you can deduce the URIs you need to authenticate
Bryan Perino
@bryantp
Jan 18 2017 14:52
Yup, not sure how I would do that dynamically though
Like, which beans I would need to override
This would also have to be done on a per request basis
Dave Syer
@dsyer
Jan 18 2017 14:53
I guess you'd have to write your own AuthorizationCodeResourceDetails and create one in your own OAuth2AuthenticationProcessingFilter
Maybe ask the UAA team for some help?
They might have had something in mind when they built it.
Bryan Perino
@bryantp
Jan 18 2017 14:54
They don't seem to do much Spring stuff, which put me in a bit of a bind.
I'll relay what we spoke about here to them though. See if someone who knows Spring is on the channel.
Dave Syer
@dsyer
Jan 18 2017 14:55
Actually that's the wrong filter to customize
You need the one that authenticates in the Boot @EnableOAUth2Sso.
OAuth2ClientAuthenticationProcessingFilter
Dave Syer
@dsyer
Jan 18 2017 15:01
You need the logic from there, but different lifecycles for the rest template and tokenservices
Bryan Perino
@bryantp
Jan 18 2017 15:01
Looking at that class, I have to provide a custom RestTemplate inside to retrieve the Access Token
Could I keep the same instance of a ResourceServerTokenServices?
and just have each request have its own Rest Template?
Dave Syer
@dsyer
Jan 18 2017 15:02
Depends how you want to get the user details
Does each UAA subdomain have a unique public key for the access tokens?
Or a unique user info endpoint?
I'm guessing probably both
Bryan Perino
@bryantp
Jan 18 2017 15:03
Not sure about the public key. I haven't done any configuring for it, so it's the default settings
endpoint will be unique due to the subdomain
Dave Syer
@dsyer
Jan 18 2017 15:04
You might get lucky with the JWT then.
Bryan Perino
@bryantp
Jan 18 2017 15:04
Essentially, I will read the default values from the application.yml, and then just append the subdomain to it in the Rest Template
Dave Syer
@dsyer
Jan 18 2017 15:04
In a AuthorizationCodeResourceDetails makes more sense to me
But broadly speaking, yes.
Bryan Perino
@bryantp
Jan 18 2017 15:07
How would I make sure a new bean is made on each request?
Would that be the Scope annotation?
Dave Syer
@dsyer
Jan 18 2017 15:10
You could probably do it with @Scope("request") and @Lazy
Actually I don't see @Lazy anywhere in the normal config, so maybe you don't need that
The AccessTokenRequest is already @Scope("request")
So you'd just be changing one thing (if you are lucky) and making the AuthorizationCodeResourceDetails also request scoped.
You'd have to be able to look up the domain inside the @Bean method that creates it.
I.e. any request must be able to be mapped to a subdomain.
Bryan Perino
@bryantp
Jan 18 2017 16:44
So, what's the relationship between OAuth2ClientAuthenticationProcessingFilter, AccessTokenRequest and AuthorizationCodeResourceDetails?
I thought all I would have to do is modify the OAuth2ClientAuthenticationProcessingFilter's OAuth2RestOperations
Dave Syer
@dsyer
Jan 18 2017 16:45
Yes, I think so. If you can do it all with request scope that should work.
The relationship is filter > rest template > (resource details, token request)
Bryan Perino
@bryantp
Jan 18 2017 16:45
Ok, so I override the OAuth2ClientAuthenticationProcessingFilter bean and scope it to request
Dave Syer
@dsyer
Jan 18 2017 16:46
That doesn't make sense
It's the AuthorizationCodeResourceDetails that is different per request
Bryan Perino
@bryantp
Jan 18 2017 16:47
The AuthorizationCodeResourceDetails is the result of a rest template call right?
Dave Syer
@dsyer
Jan 18 2017 16:47
No it's one of the dependencies of the rest template.
Bryan Perino
@bryantp
Jan 18 2017 16:47
Ok, so it contains the information to make the call
Like the URL
Dave Syer
@dsyer
Jan 18 2017 16:48
Yes. And in a Spring Boot app there is a singleton bean of that type.
You goal is to make it request scope
(and put some logic in it)
Bryan Perino
@bryantp
Jan 18 2017 16:48
Ah, ok. So I don't need to really override anything else.
Just that bean and scope it to request
Hopefully
Dave Syer
@dsyer
Jan 18 2017 16:48
Probably
You need a way for it to determine the domain from the request
I guess whether or not that is possible without additional beans is implementation detail
Bryan Perino
@bryantp
Jan 18 2017 17:07
So, I am having a little trouble overriding the AuthorizationCodeResourceDetails bean
It never seems to be created
Here is the code:
@Configuration
public class TenantAwareAuthFactory {

    private static Logger log = LoggerFactory.getLogger(TenantAwareAuthFactory.class);


    @Bean
    @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public AuthorizationCodeResourceDetails authorizationCodeResourceDetails(){
        log.info("Creating new Authorization Code Resource Details");
        return new AuthorizationCodeResourceDetails();
    }
}
The default one is always created instead
Bryan Perino
@bryantp
Jan 18 2017 17:12
Is the AuthorizationCodeResourceDetails created via injection or manually instantiated?
If it is, I guess that means I have to override a different bean?
Dave Syer
@dsyer
Jan 18 2017 17:19
Yeah the default one is not conditional. So overriding it is going to be more complicated.
You might have to extend OAuth2ClientConfiguration and include your bean in that or something
You can read the conditions in OAuth2RestOperationsConfiguration (and friends) and try to figure it out from there.
As a last resort (or a way to get it working to see if it is going to fly) you could write a BeanPostProcessor that replaces the existing default instance with the one that you create.
Bryan Perino
@bryantp
Jan 18 2017 19:28
I'm getting a Possible CSRF detected - state parameter was required but no state could be found error whenever I try to authenticate
Using this url to authenticate http://coke.uaa.mydomain.io:8080/uaa/oauth/authorize?client_id=store-ui&redirect_uri=http://dashboard.mydomain.io:8082/login&response_type=code&scope=openid%20uaa.admin%20uaa.user&code=MPvGxW
Bryan Perino
@bryantp
Jan 18 2017 20:25
Where is this state supposed to come from?
Dave Syer
@dsyer
Jan 18 2017 21:59
from the session
Is the session for mydomain.io?
Look at the cookies in your browser
Bryan Perino
@bryantp
Jan 18 2017 22:01
Well, I am using the authorize url, which redirects me to the login page
Dave Syer
@dsyer
Jan 18 2017 22:02
That's not what I said
Look at the cookies
You need to have a distinct cookie for the UAA and your app
If they collide (same host, no path), then the state gets lost
You are basically trying to store two sessions under the same key
Normally in CF the UAA has a different domain at least
Bryan Perino
@bryantp
Jan 18 2017 22:04
Ah, I see
subdomains don't count I guess
Let me check
Dave Syer
@dsyer
Jan 18 2017 22:07
If you look in the browser and there's only one cookie that's a problem
Either the UAA are your app cookie. Or the app sessions are not working.
Even if there are 2 cookies the app could be scaled up and not handling sessions correctly
Anyway, the sessions in your client app are foobar.
I guess you can figure out why
Bryan Perino
@bryantp
Jan 18 2017 22:12
hosts are unique per cookie
I am seeing coke.uaa.mysite.io and dashboard.mysite.io