You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Sergey Beryozkin <sb...@gmail.com> on 2012/08/01 14:35:45 UTC

Re: Kerberos authentication using delegation from Principal Ticket

Hi All

I've linked to this thread from
https://cwiki.apache.org/confluence/display/CXF20DOC/Client+HTTP+Transport+%28including+SSL+support%29#ClientHTTPTransport%28includingSSLsupport%29-CredentialDelegation

Thanks, Sergey

On 19/07/12 23:30, Josef Bajada wrote:
> Hi Christian,
>
> Well, I guess yes and no.
>
> a) The server is secured and the account of the server has to be flagged as trusted to delegate credentials. That is important for things to work, so the server must be in an environment where its reasonably secured and trusted. In our case this application is an Intranet one which is already handling sensitive data. Its secured and trusted as much as Exchange (its handling Sharepoint documents and records on behalf of users).
>
> b) Once the GSSCredential is obtained from the application it cannot be generated again. If you try to save the Token data from the Header and regenerate the GSSCredential from a new GSSContext you will get an error that there is a replay attempt. So in reality only the GSSCredential you have in memory associated with that Principal and Servlet Request can be used. I think there are also lifetime limits on the GSSCredential.
>
> c) Not sure what you are referring to with regards to forwarding the TGT vs using the STS approach. We are still generating a new ticket from a new GSSContext. We are using the original GSSCredential object just to obtain a new token from the KDC. Not sure if this is in fact the STS approach. It could also be that our web application could be restricted with regards to which SPNs it can request tickets for. So just to explain whats happening, the process is as follows:
>
> 1. User uses his browser to access our intranet web application.
> 2. Tomcat replies with 401 Negotiate
> 3. Browser gets the user's account info and sends a Kerberos Token in the HTTP header, which is contains a ticket which is marked Forwardable (does not mean any one can use it).
> 4. Tomcat 7 SPNEGO Authenticator uses GSS API to decode the ticket and get a GSSCredential object.
> 5. The GSSCredential object is passed to the Tomcat Realm, which could try to use it (also via the delegation process) to authorise the user credentials.
> 6. The Tomcat 7 RealmBase stores the GSSCredential in the Tomcat 7 GenericPrincipal, which is available from the HttpServletRequest.
> 7. Spring puts the HttpServletRequest available in a ThreadLocal object and can be retrieved statically through the RequestContextHolder.
> 8. When the application performs a web service call via CXF, the custom Spnego AuthSupplier is invoked.
> 9. The GSSCredential in the request is used to instantiate a new GSSContext using the GSSCredential and the target SPN.
> 10. A new token is obtained through initiating a new Security Context (initSecContext()). At this point the KDC might refuse to give us a Token if the application is not permitted to get a delegate Kerberos ticket for that SPN.
>
> Obviously the application has to be explicitly trusted to do this and has to be secured together with the environment its running on using the normal security measures to protect any server carrying sensitive corporate data.
>
> Best regards,
>
> Josef
>
>
> -----Original Message-----
> From: Christian Schneider [mailto:cschneider111@gmail.com] On Behalf Of Christian Schneider
> Sent: 19 July 2012 21:54
> To: users@cxf.apache.org
> Subject: Re: Kerberos authentication using delegation from Principal Ticket
>
> That sounds very interesting as it is a quite simple solution. It might have some securtiy implications though. Still it might be interesting to describe this for other users.
>
> If I remember correctly then the only way to achieve delegation without MS Extensions is to send the forwardable Ticket Granting Ticket in the request. If that is true for your case you should be aware that this means the server can fully impersonate the user. This means it can access his mail on an Exchange server, access all his files, ... This is a high security risk.
>
> A more secure way might be the STS aproach were the server can request a Service Ticket on behalf of the user at the STS Server using the ST it got. So the STS Server can have rules which resources the server may access on behalf of the user. Of course this solution is a lot more complicated.
>
> Christian
>
> Am 19.07.2012 20:37, schrieb Josef Bajada:
>> Hi all,
>>
>> First of all I wanted to thank you all for your prompt replies and efforts to propose a solution.
>> We've just managed to find a (quite simple) solution that works well and also does not require any additional code to take care of it within the business logic.
>> I'm explaining what we did here in case someone needs to do it and finds this thread.
>>
>> It also proves that Kerberos delegation also works well in Java
>> without MS extensions :)
>>
>> Unfortunately the solution depends on Tomcat (7 or greater) and Spring.
>>
>> What we did is that we wrote our own AuthSupplier, lets call it TomcatPrincipalSpnegoAuthSupplier.
>>
>> What this does is:
>>
>> //the following is Spring dependent
>> HttpServletRequest request = ((ServletRequestAttributes)
>> RequestContextHolder.getRequestAttributes()).getRequest();
>>
>> //the following is Tomcat dependent
>> GenericPrincipal  principal = (GenericPrincipal)
>> request.getUserPrincipal();
>>
>> //Tomcat 7 introduced Spnego auth, and with it the method
>> getGssCredential() in GenericPrincipal which is populated by RealmBase
>> if the ticket can be used for delegation GSSCredential
>> delegateCredential = principal.getGssCredential();
>>
>>   From then on one can use the normal GSSManager, GSSContext and GSSName etc. to request the new token based on the existent GSSCredential from the KDC.
>> (Refer to the existent SpnegoAuthSupplier how to do it, Sergey's
>> latest commit includes the code to request a token based on an
>> existent GSSCredential and a specified SPN)
>>
>> In the<jaxws:client>  definition in the application context we then put:
>> <http:conduit ...>
>>       ...
>>       <http:authSupplier
>> class="my.package.TomcatPrincipalSpnegoAuthSupplier"/>
>> </http:conduit>
>>
>> That way the business logic using the JAX-WS client does not have to do anything, and does not even know it is being authenticated using Kerberos delegation.
>>
>> One final thing one needs to make sure that the client is sending a Kerberos ticket which is forwardable and the application's account is flagged as 'Account is Trusted for Delegation', otherwise you'll be going around in circles.
>>
>> We'll need to make some null and instanceof checks for the AuthSupplier before we go with it into production, and for it to work in instances when its not being called from within a Servlet Request context (separate worker thread or whatever), in which case it makes sense to fall back to the default SpnegoAuthSupplier. I see that Sergey has just split the SpnegoAuthSupplier to extend a separate AbstractSpnegoAuthSupplier so it might make sense to also extend that in our Tomcat specific one, once it becomes available on the stable release of CXF.
>> Our code would then just be the above 3 lines and if the request, principal and delegateCredential are not null we create the GSSContext  and call getToken(authPolicy, gsscontext), otherwise we just do super.getAuthorization(), or something along these lines.
>>
>> Not sure how we could go about making this functionality available in CXF given its dependence on Tomcat, however it would be great to include it out of the box in CXF.
>>
>> Thanks again, hope this thread helps others who try to achieve the same thing.
>>
>>
>> Regards,
>>
>> Josef Bajada
>> Senior Technical Architect
>> GO
>>
>> GO, Fra Diego Street, Marsa, MRS 1501, Malta.
>> t  +356 2594 6826     f  +356 2124 0112
>> w www.go.com.mt
>>
>> This email and any files or content transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited. The Company and the originator of this email accept no liability for the content of this email, or for the consequences of any actions taken on the basis of the information provided, unless that information is subsequently confirmed in writing. If you are not the intended recipient you are notified that disclosing, copying, 
 d
istributing or taking any action in reliance on the contents of this information is strictly prohibited.
>>
>> Warning: Although the Company and the originator  have taken reasonable precautions to ensure no viruses are present in this email, the company cannot accept responsibility for any loss or damage arising from the use of this email or attachments.
>>
>>
>>
>>
>>
>>
>> -----Original Message-----
>> From: Christian Schneider [mailto:cschneider111@gmail.com] On Behalf
>> Of Christian Schneider
>> Sent: 19 July 2012 17:49
>> To: users@cxf.apache.org
>> Subject: Re: Kerberos authentication using delegation from Principal
>> Ticket
>>
>> I think an interceptor like you proposed might be the best solution long term as it allows to keep the auth stuff out of the business code.
>>
>> Christian
>>
>> Am 19.07.2012 17:31, schrieb Sergey Beryozkin:
>>> Hi Christian
>>> On 19/07/12 06:53, Christian Schneider wrote:
>>>> I don´t think a static gssCredential in the spring config can help.
>>>> The credentials may be different on each call.
>>>>
>>> I thought Spring would be able to offer some per-request wrapper :-)
>>>
>>>> Instead I think we need to set the property on the client just
>>>> before the call. This is how it would look in the wsdl_first example:
>>>>
>>>> org.apache.cxf.endpoint.Client client =
>>>> org.apache.cxf.frontend.ClientProxy.getClient(customerService);
>>>> client.setThreadLocalRequestContext(true);
>>>> Map<String, Object>  reqContext = client.getRequestContext();
>>>> reqContext.put("org.ietf.jgss.GSSCredential", gssCredentials);
>>>> customers = customerService.getCustomersByName("Smith");
>>>>
>>>> Not sure if this works but it should be worth a try.
>>>>
>>> Yeah, that is possible too - another option is to get a GSSCredential
>>> retrieved from within a custom out interceptor (itself registered
>>> from
>>> Spring) and then set it on a current message. I guess much depends on
>>> the way the credential can be actually obtained from the original
>>> SecurityContext which Tomcat and/or Spring Sec create, lets see what
>>> solution Josef will find :-).
>>>
>>> Cheers, Sergey
>>>
>> --
>> Christian Schneider
>> http://www.liquid-reality.de
>>
>> Open Source Architect
>> Talend Application Integration Division http://www.talend.com
>>
>>
>> Josef Bajada
>> Senior Technical Architect
>> GO
>>
>> GO, Fra Diegu Street, Marsa, MRS 1501.
>> t   +356 2594 6826
>> ________________________________
>
>
> --
>
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> Talend Application Integration Division http://www.talend.com
>
>
>
> Josef Bajada
> Senior Technical Architect
> GO
>
> GO, Fra Diegu Street, Marsa, MRS 1501.
> t   +356 2594 6826
> ________________________________


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Kerberos authentication using delegation from Principal Ticket

Posted by Daniel Kulp <dk...@apache.org>.
On Wednesday, August 01, 2012 01:12:31 PM Josef Bajada wrote:
> Nice!
> 
> Sergey, is it maybe possible to have getToken() (line 130 I think) split
> into 2 methods, with the second one taking the GSSCredential as a
> parameter and being protected rather than private? So the second
> getToken() would look like private getToken(GSSCredential delegatedCred
> ...) and contain the lines from 138 onwards.

Patches are always welcome.....   ;-)

Seriously, in these types of cases, its usually better to have someone that 
is actually creating a subclass or similar create a patch that makes sure 
the stuff in CXF really is refactored enough to be useful.  Saves a lot of 
back and forth.

Dan



> 
> This would be easier for whoever is extending the
> AbstractSpnegoAuthSupplier to use it with delegated credentials, since
> what GSS provides is in fact a GSSCredential object. (It is also in the
> Tomcat 7's principal). So when implementing the custom AuthSupplier in
> the case where the GSSCredential is available one would just call the
> getToken() suggested above.
> 
> Thanks!
> 
> Josef
> 
> 
> 

-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com

RE: Kerberos authentication using delegation from Principal Ticket

Posted by Josef Bajada <Jo...@go.com.mt>.
Nice!

Sergey, is it maybe possible to have getToken() (line 130 I think) split into 2 methods, with the second one taking the GSSCredential as a parameter and being protected rather than private? So the second getToken() would look like private getToken(GSSCredential delegatedCred ...) and contain the lines from 138 onwards.

This would be easier for whoever is extending the AbstractSpnegoAuthSupplier to use it with delegated credentials, since what GSS provides is in fact a GSSCredential object. (It is also in the Tomcat 7's principal). So when implementing the custom AuthSupplier in the case where the GSSCredential is available one would just call the getToken() suggested above.

Thanks!

Josef





-----Original Message-----
From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
Sent: 01 August 2012 14:36
To: users@cxf.apache.org
Cc: Josef Bajada
Subject: Re: Kerberos authentication using delegation from Principal Ticket

Hi All

I've linked to this thread from
https://cwiki.apache.org/confluence/display/CXF20DOC/Client+HTTP+Transport+%28including+SSL+support%29#ClientHTTPTransport%28includingSSLsupport%29-CredentialDelegation

Thanks, Sergey

On 19/07/12 23:30, Josef Bajada wrote:
> Hi Christian,
>
> Well, I guess yes and no.
>
> a) The server is secured and the account of the server has to be flagged as trusted to delegate credentials. That is important for things to work, so the server must be in an environment where its reasonably secured and trusted. In our case this application is an Intranet one which is already handling sensitive data. Its secured and trusted as much as Exchange (its handling Sharepoint documents and records on behalf of users).
>
> b) Once the GSSCredential is obtained from the application it cannot be generated again. If you try to save the Token data from the Header and regenerate the GSSCredential from a new GSSContext you will get an error that there is a replay attempt. So in reality only the GSSCredential you have in memory associated with that Principal and Servlet Request can be used. I think there are also lifetime limits on the GSSCredential.
>
> c) Not sure what you are referring to with regards to forwarding the TGT vs using the STS approach. We are still generating a new ticket from a new GSSContext. We are using the original GSSCredential object just to obtain a new token from the KDC. Not sure if this is in fact the STS approach. It could also be that our web application could be restricted with regards to which SPNs it can request tickets for. So just to explain whats happening, the process is as follows:
>
> 1. User uses his browser to access our intranet web application.
> 2. Tomcat replies with 401 Negotiate
> 3. Browser gets the user's account info and sends a Kerberos Token in the HTTP header, which is contains a ticket which is marked Forwardable (does not mean any one can use it).
> 4. Tomcat 7 SPNEGO Authenticator uses GSS API to decode the ticket and get a GSSCredential object.
> 5. The GSSCredential object is passed to the Tomcat Realm, which could try to use it (also via the delegation process) to authorise the user credentials.
> 6. The Tomcat 7 RealmBase stores the GSSCredential in the Tomcat 7 GenericPrincipal, which is available from the HttpServletRequest.
> 7. Spring puts the HttpServletRequest available in a ThreadLocal object and can be retrieved statically through the RequestContextHolder.
> 8. When the application performs a web service call via CXF, the custom Spnego AuthSupplier is invoked.
> 9. The GSSCredential in the request is used to instantiate a new GSSContext using the GSSCredential and the target SPN.
> 10. A new token is obtained through initiating a new Security Context (initSecContext()). At this point the KDC might refuse to give us a Token if the application is not permitted to get a delegate Kerberos ticket for that SPN.
>
> Obviously the application has to be explicitly trusted to do this and has to be secured together with the environment its running on using the normal security measures to protect any server carrying sensitive corporate data.
>
> Best regards,
>
> Josef
>
>
> -----Original Message-----
> From: Christian Schneider [mailto:cschneider111@gmail.com] On Behalf
> Of Christian Schneider
> Sent: 19 July 2012 21:54
> To: users@cxf.apache.org
> Subject: Re: Kerberos authentication using delegation from Principal
> Ticket
>
> That sounds very interesting as it is a quite simple solution. It might have some securtiy implications though. Still it might be interesting to describe this for other users.
>
> If I remember correctly then the only way to achieve delegation without MS Extensions is to send the forwardable Ticket Granting Ticket in the request. If that is true for your case you should be aware that this means the server can fully impersonate the user. This means it can access his mail on an Exchange server, access all his files, ... This is a high security risk.
>
> A more secure way might be the STS aproach were the server can request a Service Ticket on behalf of the user at the STS Server using the ST it got. So the STS Server can have rules which resources the server may access on behalf of the user. Of course this solution is a lot more complicated.
>
> Christian
>
> Am 19.07.2012 20:37, schrieb Josef Bajada:
>> Hi all,
>>
>> First of all I wanted to thank you all for your prompt replies and efforts to propose a solution.
>> We've just managed to find a (quite simple) solution that works well and also does not require any additional code to take care of it within the business logic.
>> I'm explaining what we did here in case someone needs to do it and finds this thread.
>>
>> It also proves that Kerberos delegation also works well in Java
>> without MS extensions :)
>>
>> Unfortunately the solution depends on Tomcat (7 or greater) and Spring.
>>
>> What we did is that we wrote our own AuthSupplier, lets call it TomcatPrincipalSpnegoAuthSupplier.
>>
>> What this does is:
>>
>> //the following is Spring dependent
>> HttpServletRequest request = ((ServletRequestAttributes)
>> RequestContextHolder.getRequestAttributes()).getRequest();
>>
>> //the following is Tomcat dependent
>> GenericPrincipal  principal = (GenericPrincipal)
>> request.getUserPrincipal();
>>
>> //Tomcat 7 introduced Spnego auth, and with it the method
>> getGssCredential() in GenericPrincipal which is populated by
>> RealmBase if the ticket can be used for delegation GSSCredential
>> delegateCredential = principal.getGssCredential();
>>
>>   From then on one can use the normal GSSManager, GSSContext and GSSName etc. to request the new token based on the existent GSSCredential from the KDC.
>> (Refer to the existent SpnegoAuthSupplier how to do it, Sergey's
>> latest commit includes the code to request a token based on an
>> existent GSSCredential and a specified SPN)
>>
>> In the<jaxws:client>  definition in the application context we then put:
>> <http:conduit ...>
>>       ...
>>       <http:authSupplier
>> class="my.package.TomcatPrincipalSpnegoAuthSupplier"/>
>> </http:conduit>
>>
>> That way the business logic using the JAX-WS client does not have to do anything, and does not even know it is being authenticated using Kerberos delegation.
>>
>> One final thing one needs to make sure that the client is sending a Kerberos ticket which is forwardable and the application's account is flagged as 'Account is Trusted for Delegation', otherwise you'll be going around in circles.
>>
>> We'll need to make some null and instanceof checks for the AuthSupplier before we go with it into production, and for it to work in instances when its not being called from within a Servlet Request context (separate worker thread or whatever), in which case it makes sense to fall back to the default SpnegoAuthSupplier. I see that Sergey has just split the SpnegoAuthSupplier to extend a separate AbstractSpnegoAuthSupplier so it might make sense to also extend that in our Tomcat specific one, once it becomes available on the stable release of CXF.
>> Our code would then just be the above 3 lines and if the request, principal and delegateCredential are not null we create the GSSContext  and call getToken(authPolicy, gsscontext), otherwise we just do super.getAuthorization(), or something along these lines.
>>
>> Not sure how we could go about making this functionality available in CXF given its dependence on Tomcat, however it would be great to include it out of the box in CXF.
>>
>> Thanks again, hope this thread helps others who try to achieve the same thing.
>>
>>
>> Regards,
>>
>> Josef Bajada
>> Senior Technical Architect
>> GO
>>
>> GO, Fra Diego Street, Marsa, MRS 1501, Malta.
>> t  +356 2594 6826     f  +356 2124 0112
>> w www.go.com.mt
>>
>> This email and any files or content transmitted with it are
>> confidential and intended solely for the use of the individual or
>> entity to whom they are addressed. This message contains confidential
>> information and is intended only for the individual named. If you are
>> not the named addressee you should not disseminate, distribute or
>> copy this e-mail. Please notify the sender immediately by e-mail if
>> you have received this e-mail by mistake and delete this e-mail from
>> your system. If you are not the intended recipient you are notified
>> that disclosing, copying, distributing or taking any action in
>> reliance on the contents of this information is strictly prohibited.
>> The Company and the originator of this email accept no liability for
>> the content of this email, or for the consequences of any actions
>> taken on the basis of the information provided, unless that
>> information is subsequently confirmed in writing. If you are not the
>> intended recipient you are notified that disclosing, copying, d
istributing or taking any action in reliance on the contents of this information is strictly prohibited.
>>
>> Warning: Although the Company and the originator  have taken reasonable precautions to ensure no viruses are present in this email, the company cannot accept responsibility for any loss or damage arising from the use of this email or attachments.
>>
>>
>>
>>
>>
>>
>> -----Original Message-----
>> From: Christian Schneider [mailto:cschneider111@gmail.com] On Behalf
>> Of Christian Schneider
>> Sent: 19 July 2012 17:49
>> To: users@cxf.apache.org
>> Subject: Re: Kerberos authentication using delegation from Principal
>> Ticket
>>
>> I think an interceptor like you proposed might be the best solution long term as it allows to keep the auth stuff out of the business code.
>>
>> Christian
>>
>> Am 19.07.2012 17:31, schrieb Sergey Beryozkin:
>>> Hi Christian
>>> On 19/07/12 06:53, Christian Schneider wrote:
>>>> I don´t think a static gssCredential in the spring config can help.
>>>> The credentials may be different on each call.
>>>>
>>> I thought Spring would be able to offer some per-request wrapper :-)
>>>
>>>> Instead I think we need to set the property on the client just
>>>> before the call. This is how it would look in the wsdl_first example:
>>>>
>>>> org.apache.cxf.endpoint.Client client =
>>>> org.apache.cxf.frontend.ClientProxy.getClient(customerService);
>>>> client.setThreadLocalRequestContext(true);
>>>> Map<String, Object>  reqContext = client.getRequestContext();
>>>> reqContext.put("org.ietf.jgss.GSSCredential", gssCredentials);
>>>> customers = customerService.getCustomersByName("Smith");
>>>>
>>>> Not sure if this works but it should be worth a try.
>>>>
>>> Yeah, that is possible too - another option is to get a
>>> GSSCredential retrieved from within a custom out interceptor (itself
>>> registered from
>>> Spring) and then set it on a current message. I guess much depends
>>> on the way the credential can be actually obtained from the original
>>> SecurityContext which Tomcat and/or Spring Sec create, lets see what
>>> solution Josef will find :-).
>>>
>>> Cheers, Sergey
>>>
>> --
>> Christian Schneider
>> http://www.liquid-reality.de
>>
>> Open Source Architect
>> Talend Application Integration Division http://www.talend.com
>>
>>
>> Josef Bajada
>> Senior Technical Architect
>> GO
>>
>> GO, Fra Diegu Street, Marsa, MRS 1501.
>> t   +356 2594 6826
>> ________________________________
>
>
> --
>
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> Talend Application Integration Division http://www.talend.com
>
>
>
> Josef Bajada
> Senior Technical Architect
> GO
>
> GO, Fra Diegu Street, Marsa, MRS 1501.
> t   +356 2594 6826
> ________________________________


--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Josef Bajada
Senior Technical Architect
GO

GO, Fra Diegu Street, Marsa, MRS 1501.
t   +356 2594 6826

w www.go.com.mt<http://www.go.com.mt>

This email and any files or content transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited. The Company and the originator of this email accept no liability for the content of this email, or for the consequences of any actions taken on the basis of the information provided, unless that information is subsequently confirmed in writing. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.

Warning: Although the Company and the originator  have taken reasonable precautions to ensure no viruses are present in this email, the company cannot accept responsibility for any loss or damage arising from the use of this email or attachments.
________________________________