[keycloak-dev] client requested account linking

Scott Rossillo srossillo at smartling.com
Sat Feb 25 18:58:42 EST 2017


Bill,

Can you provide a browser flow of what you’re trying to accomplish?

Scott Rossillo
Smartling | Senior Software Engineer
srossillo at smartling.com

> On Feb 25, 2017, at 9:42 AM, Bill Burke <bburke at redhat.com> wrote:
> 
> Ok, I changed this again.  Any solution we come up with will require 
> that the application protect itself from CSRF for this operation.  
> There's nothing really the server can do. We can give guidelines on how 
> to accomplish this.  So, instead of this handshake, there will only be 
> one GET request to a link url that takes client_id, redirect_uri, nonce, 
> and hash query parameters.
> 
> The nonce will be a random string sent by the client.  The hash will be 
> a base64url encoded SHA_256 hash of nonce + clientSessionId.  The server 
> will verify this hash by looking for an SSO cookie, matching it up with 
> a UserSession, then looping through ClientSessionModels to find a 
> matching clientId then creating and matching the hash.  This is combined 
> with not allowing CORS preflight requests to this URL  (protects SSO 
> cookie) as well as checking that any Origin header matches the client.  
> I think this is enough to ensure that this server URL is protected from 
> direct CSRF attacks.
> 
> 
> On 2/24/17 8:46 PM, Bill Burke wrote:
>> Ok, option #3 where I would pass an access token to initiate the link
>> won't work as the access token could be leaked by a CSRF attack on the
>> client.  My new solution is to do a custom protocol.  The goal of this
>> protocol is for the server to verify that the client initiated the
>> account link and not some rogue site.
>> 
>> 1. Client does a background bearer-token authenticated to the Keycloak
>> operation /initiate-link using the access token it got from login.
>> 
>> 2. /initiate-link gets the ClientSessionModel associated with the
>> bearer-token. It generates a server-nonce and stores it within the
>> ClientSessionModel.
>> 
>> 3. keycloak /initiate-link returns a response that contains the server-nonce
>> 
>> 4. Client generates its own client-nonce.  This client-nonce is stored
>> in its HttpSession.
>> 
>> 5. Client generates a nonce-hash of server-nonce + client-nonce +
>> provider-id.
>> 
>> 6. Client redirects the browser to Keycloak /link operation passing the
>> client-nonce, nonce-hash, provider-id, client-id, and redirect-uri as
>> query parameters.
>> 
>> 7. Keycloak /link operation validates that the browser is logged in.  If
>> the user is not logged, an error page is shown.  We DO NOT redirect back
>> to the client when there is an error as this is an attack vector.
>> 
>> 8. Keycloak verifies clientid, redirect uri, and provider id.
>> 
>> 9. Keycloak loops through the browser's UserSessionModel looking for
>> ClientSessionModels that match the clientId.  Checks to see if this
>> ClientSession has a server-nonce within it.  If so, it validates the
>> hash.  We DO NOT redirect back to the client when there is an error as
>> this is an attack vector.  The server-nonce client session attribute is
>> cleared so that it can only be used once.
>> 
>> 10. Keycloak initiates the social provider login
>> 
>> 11. Keycloak redirects back to the client using the redirect_uri
>> 
>> What isn't protected here is the client.  If the client is a traditional
>> web app, the client is responsible for protecting itself from CSRF.  The
>> Account Service does this with a cookie nonce plus the nonce in the
>> rendered page links, and it also rejects any CORS requests.  The client
>> app will have to do this too.  I don't think Javascript apps are
>> affected unless there is a URL you can redirect to that triggers this flow.
>> 
>> Again, I'm not even sure we have to do this sort of thing.  All a CSRF
>> attack could do is request that the user link their Keycloak account.
>> The attacker can't get any information about the user.
>> 
>> 
>> 
>> On 2/24/17 9:10 AM, Bill Burke wrote:
>>> Account linking *MUST* be browser based as you need to delegate
>>> authentication to the IDP you are brokering with.
>>> 
>>> 
>>> On 2/24/17 3:21 AM, Marek Posolda wrote:
>>>> Don't we have a plan to rewrite AccountService to use Angular+REST? If
>>>> yes, then we are fine though. We will have REST endpoint for link
>>>> broker, which can be invoked with the bearer token as long as the
>>>> token has "manage-account" scope. We don't need to care about CSRF then.
>>>> 
>>>> I can see the only reason to keep support browser+cookie based flows -
>>>> the case when client application doesn't have Keycloak token. But from
>>>> what you mentioned in the last paragraph, it looks that their client
>>>> has our access token?
>>>> 
>>>> Marek
>>>> 
>>>> 
>>>> On 23/02/17 23:24, Bill Burke wrote:
>>>>> A customer has asked us to implement a feature in which there is a
>>>>> browser endpoint on keycloak.  This URL can be told to link to a
>>>>> specific identity broker provider (Google, Facebook, etc.) and then the
>>>>> browser would be redirected back to the client. Pretty much what exists
>>>>> in the Account Service console, but without having to look at the
>>>>> Account Service.  The reason for this is that they are doing integration
>>>>> with a specific social provider and don't want to have to go through the
>>>>> Account Service pages. Seems pretty reasonable and valid use case...
>>>>> I'm worried about a couple of things:
>>>>> 
>>>>> * The design of it
>>>>> 
>>>>> * The security implications.
>>>>> 
>>>>> The implementation would be simple enough, it would just extract code
>>>>> from the accoutn service.  The endpoint would take a "providerId"
>>>>> paramter that would be the idp linking to, a "clientId" for the client
>>>>> requesting the link, and a "redirect_uri" to redirect back to after the
>>>>> link is successful. Obviously the redirect_uri would be validated
>>>>> against the clientId.
>>>>> 
>>>>> Now comes the interesting part, the security implications. Account
>>>>> linking in the Account Service is fine and dandy and doesn't have any
>>>>> security holes because we guarantee that the Account Service initiated
>>>>> the linking via a CSRF check.  For this new Client-Requested-Linking
>>>>> feature, if we do nothing, and just model it as above, we cannot
>>>>> guarantee that the client initiated the linking request.  What are the
>>>>> implications of this?  This feature would be vulnerable to CSRF.  A
>>>>> rogue website could initiate account linking to a specific configured
>>>>> provider.  Is this bad?  I don't know.  We can guarantee that the
>>>>> redirect uri is valid.  The browser would never get back to the rogue
>>>>> website. So what can we do to improve this?
>>>>> 
>>>>> * We could do nothing and hope its ok that anybody can initiate a link.
>>>>> 
>>>>> * We could add a consent screen like this: "Application 'clientId' is
>>>>> requesting that you link your user account to 'providerId'.  Do you
>>>>> agree to this?  You will be redirected to this provider if you click
>>>>> ok.".  This of course relies on the user to actually read the page.  Is
>>>>> this good enough?
>>>>> 
>>>>> * My last thought would be OIDC specific.  We could use the POST binding
>>>>> trick that SAML does to do a browser redirect via a POST call. THe POST
>>>>> would contain the access token the client has.  We match this token up
>>>>> against the browser cookie to make sure its the same session. We also
>>>>> make sure that the access token has permission to request a link.  There
>>>>> are 2 downsides to this approach a) This requires some code on the
>>>>> client side to obtain the access token and then to package it up into an
>>>>> HTML document so the POST binding trick can be done.  b) This will only
>>>>> work for OIDC clients.  SAML clients will be left in the dust, although
>>>>> I guess we could allow SAML to push a signed assertion back.
>>>>> 
>>>>> 
>>>>> Thoughts?
>>>>> 
>>>>> 
>>>>> _______________________________________________
>>>>> keycloak-dev mailing list
>>>>> keycloak-dev at lists.jboss.org
>>>>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>>> _______________________________________________
>>> keycloak-dev mailing list
>>> keycloak-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>> _______________________________________________
>> keycloak-dev mailing list
>> keycloak-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
> 
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-dev



More information about the keycloak-dev mailing list