Hi, I'm a bit lost: how the principal provided in Subject.doAs should become available in request.getPrincipalUser() ?
I've done one more debugging session, but unsuccessfully. I'm confident the flow is correct. Let me resume what I understand one more time: - I call https://127.0.0.1:8443/gateway/sandbox/webhdfs/v1/tmp?op=LISTSTATUS, the SSOCookieProvider redirects me to https://127.0.0.1:8443/gateway/idp/api/v1/websso?originalUrl=https://127.0.0.1:8443/gateway/sandbox/webhdfs/v1/tmp?op=LISTSTATUS - on this url, the pac4j provider is called first (before the KnoxSSO service), the current url is saved before redirecting to the CAS server where I log in - back to the callback url ( https://127.0.0.1:8443/gateway/idp/api/v1/websso?client_name=CasClient&ticket=ST-9-W12oWBh63C5Eub7IWNlj-cas01.example.org), the pac4j provider is called again before the KnoxSSO service, deals with the authentication process, saved the current user profile in a cookie and redirects to the originally requested url - on the originally requested url ( https://127.0.0.1:8443/gateway/idp/api/v1/websso?originalUrl=https://127.0.0.1:8443/gateway/sandbox/webhdfs/v1/tmp?op=LISTSTATUS), the pac4j provider is called again, which retrieves the current user profile and grants access that's why we go to the Pac4jIdentityAdapter, which retrieves the current user profile and perform a doAs. Then, it dives into the Knox plumbery and there must be something wrong happening. In the Subject.doAs called in Pac4jIdentityAdapter, the request is a XForwardedHeaderRequestWrapper and the request.getUserPrincipal() is null. The CommonIdentityAssertionFilter is called (line 58), the request is the same and the subject found is correct, the request is wrapped by a IdentityAsserterHttpServletRequestWrapper. In the AbstractIdentityAssertionFilter (line 100), the request is the wrapped one, the currentSubject is the right one. Then, I'm not sure what should happen in the source code, but the doFilterInternal method is called (in the continueChainAsPrincipal method). Finally, the ServletContainer filter is called to delegate to the WebSsoResource where request.getUserPrincipal returns null. Do you see something wrong in the latest steps ? I think it would really help if you could debug it yourself. Clone my repo: git clone https://github.com/leleuj/knox leleujknox, switch to the branch: git checkout pac4j, build everything, deploy knox, start in debug, start the debugger in your favorite IDE, call: https://127.0.0.1:8443/gateway/sandbox/webhdfs/v1/tmp?op=LISTSTATUS. The login must be the same as the password on the CAS server (an online one). Then a breakpoint in the Pac4jIdentityAdapter line 63 is a good starting point. Thanks. Best regards, Jérôme 2015-12-01 19:38 GMT+01:00 larry mccay <[email protected]>: > Hi Jérôme - > > I am trying to figure out why you aren't getting the username in > WebSSOResource. > If the default identity-assertion provider is indeed in place then you > should get it. > > Is the pac4j identity adapter filter in the same request processing as the > websso resource? > Not an easily asked question - let me try and be clear... > > Perhaps, you are pivotting during the OAuth handshake and a new request > comes in which never makes it to WebSSOResource but sets the security > context and when control gets back to the original request processing that > context is no longer there? > > Does that make any sense? > > thanks, > > --larry > > > On Tue, Dec 1, 2015 at 11:15 AM, Jérôme LELEU <[email protected]> wrote: > > > Hi, > > > > 1) About the identity-assertion provider, I don't understand what its > role > > is. I added it in my idp.xml topology but unsuccessfully: > > > > > https://github.com/apache/knox/pull/2/files#diff-4ea9a9a5ee5968f29982478512a63c54R40 > > Though, I still don't have any principal. I have a log telling me the > user > > profile is retrieved in the Pac4jIdentityAdapter (before the doAs), but > the > > user principal is not retrieved from the request in the KnoxSSO service: > > > > > https://github.com/apache/knox/blob/master/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResource.java#L149 > > > > Am I wrong in the identity-assertion provider configuration? Where > should I > > investigate? > > > > 2) Several things go into the web session: tokens (for example for OAuth > > 1.0), flow information (like the authentication has already been > performed > > to avoid infinite loop), authenticated user profile... > > I need to protect these information and share them among all the gateway > > instances. To share them, I save them in cookies and to protect them, I > > encrypt them. > > > > Notice that there is a new concept of SessionStore in pac4j and j2e-pac4j > > with a specific implementation for Knox (the session is stored into > > cookies) and we could save these session information almost anywhere, > like > > in a clustered cache like Redis or Memcache for example. I'm not too > > ambitious for this first version though. > > > > The encryption now works. My only question is about the generated > password: > > will it be different for each gateway instance? I'm expecting to have the > > same password as the encrypted cookies are shared. > > > > Thanks. > > Best regards, > > Jérôme > > > > > > > > > > 2015-11-25 14:18 GMT+01:00 larry mccay <[email protected]>: > > > > > inline... > > > > > > On Wed, Nov 25, 2015 at 5:04 AM, Jérôme LELEU <[email protected]> > wrote: > > > > > > > Hi, > > > > > > > > Thanks for all your help. I've made the pac4j integration works in > Knox > > > > (using a simple basic auth where login = pwd or a remote CAS server). > > > > > > > > > > > Great! > > > > > > > > > > I have two points left (before more tests and documentation): > > > > > > > > 1) In my Pac4jIdentityAdapter, I successfully retrieved the > > authenticated > > > > user and perform a doAs with it, but I still end with an error 500. > > > Putting > > > > a breakpoint in the WebSSOResource, I get null as the authenticated > > > > user (*Principal > > > > p *= (*(HttpServletRequest)request).getUserPrincipal();*). Doing more > > > > debugging, I see that the original request in my Pac4jIdentityAdapter > > is > > > > a XForwardedHeaderRequestWrapper, then a filter is > > > > called: RegexIdentityAssertionFilter which encapsulates the request > in > > a > > > > new one: IdentityAsserterHttpServletRequestWrapper. So I don't > > understand > > > > why this filter comes into play and why my authenticated subject is > > > "lost". > > > > > > > > > > > The fact that you are getting the RegExIdentityAssertionFilter sort of > > > points to an issue in your > > > topology. Unless you have purposely configured the regex provider. > > > > > > Make sure that you have configuration that looks like this in your > > > topology: > > > > > > <provider> > > > <role>identity-assertion</role> > > > <name>Default</name> > > > <enabled>true</enabled> > > > </provider> > > > > > > > > > > > > > 2) To save session data, I use cookies: for each key, I have a cookie > > > whose > > > > value is the serialized object in base64. I don't think it's secure > > > enough, > > > > especially for the authenticated user profile. I think I could use > the > > > > JWTokenAuthority to wrap data in a token: does it make sense to use > it? > > > Is > > > > there any other way to secure data? What's your recommendation / > > > > expectation? In a token, it seems I can only set a subject, issuer, > > > > audience and no extra attributes: am I getting it right? > > > > > > > > > > > What keys do you need to store in "session"? > > > Putting them in a JWT token in a cookie won't really make it any more > > > secure. > > > > > > They are signed but not encrypted. > > > We could extend the tokenAuthority to use encrypted tokens as well if > > > really needed. > > > And you could put them in the generic claims of the token. > > > However, this is all pretty much a misuse of the token that is supposed > > to > > > represent an identity or authentication event. > > > > > > There is another gatewayService that you could use called the > > CryptoService > > > - you get to this the same way that you get to the > > > tokenAuthority, aliasService, etc. > > > > > > You could provision a password from your provider contributor - see: > > > > > > > > > > > > https://github.com/apache/knox/blob/539557c902404529c4636bfe0425ba44980cc177/gateway-provider-rewrite-step-encrypt-uri/src/main/java/org/apache/hadoop/gateway/encrypturi/impl/EncryptUriDeploymentContributor.java > > > > > > The initializeContribution method initiates the creation of an > > > alias/password to be used for password based encryption later while > > > protecting internal URL details. > > > > > > Note the simple injection of the AliasService just by adding a > > > setAliasService method to the contributor. > > > > > > Then in EncryptUriProcessor you will find the runtime use of that > > password > > > for PBE in: > > > > > > > > > > > > https://github.com/apache/knox/blob/33bb1ce5727a54721baec0125dd1254d275160ac/gateway-provider-rewrite-step-encrypt-uri/src/main/java/org/apache/hadoop/gateway/encrypturi/impl/EncryptUriProcessor.java > > > > > > Note the lookup of the cryptoService.initialize() and its use in the > > > encode(). > > > > > > This will certainly allow you to protect the keys within cookies - if > > that > > > is what you are looking to do. > > > > > > I updated the pull request with my latest source code: > > > > https://github.com/apache/knox/pull/2 > > > > > > > > Thanks. > > > > Best regards, > > > > Jérôme > > > > > > > > > > > > > > > > > > Hope that is helpful. > > > > > > --larry > > > > > >
