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.