You mean an keycloak auth flow? I was thinking the same thing. Or do
you want to know how the HTTP request flow is?
1. Redirect from client:
Location:
2. Server extracts SSO cookie from GET request to obtain UserSession.
Validates client_id and redirect_uri. Calculates and validates hashes.
3. Do regular account link logic that already exists
4. Redirect to social provider
5. Redirect Back to Keycloak
6. Redirect to "redirect_uri" provided in step #1
On 2/25/17 6:58 PM, Scott Rossillo wrote:
Bill,
Can you provide a browser flow of what you’re trying to accomplish?
Scott Rossillo
Smartling | Senior Software Engineer
srossillo(a)smartling.com <mailto:srossillo@smartling.com>
> On Feb 25, 2017, at 9:42 AM, Bill Burke <bburke(a)redhat.com
> <mailto:bburke@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(a)lists.jboss.org
<mailto:keycloak-dev@lists.jboss.org>
>>>>>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
>>> _______________________________________________
>>> keycloak-dev mailing list
>>> keycloak-dev(a)lists.jboss.org <mailto:keycloak-dev@lists.jboss.org>
>>>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
>> _______________________________________________
>> keycloak-dev mailing list
>> keycloak-dev(a)lists.jboss.org <mailto:keycloak-dev@lists.jboss.org>
>>
https://lists.jboss.org/mailman/listinfo/keycloak-dev
>
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev(a)lists.jboss.org <mailto:keycloak-dev@lists.jboss.org>
>
https://lists.jboss.org/mailman/listinfo/keycloak-dev