3

We are currently implementing a Single Page Application (Angular2) and thus have run into the standard "how do we secure our backend API" problem.

The standard solution to this apparently to use the OAuth2 Implicit Grant Flow, which is all fine. We are implementing an custom Authorization Server which authenticates using our Web SSO Solution (Open AM/SAML), checks for licenses, and then issues Access Tokens via the API Gateway (Mashape Kong).

The Access Token is (as specified in the OAuth2 Implicit Flow) passed back to the SPA using a redirect, giving the access token in the fragment (https://my.spa.com/#access_token=asdfasdf&token_type=bearer&expires_in=1800).

So far, no specialties. Now: The access token is only valid for a short period of time, and there is no refresh token; we do not want the end user to actually be redirected to the Authorization Server again (it would look bad/flicker/...). Our idea was to use the existing session with the Authorization Server (which we implemented, see above) to refresh the access token (create a new one) via a CORS call to a special end point of the Authorization Server (let's call it /heartbeat).

Obviously, this requires a couple of things to be done:

  • The Origin needs to be exactly the calling application's host, and the Auth Server needs to verify and reflect that in the preflight response
  • The client application needs to do the CORS call with activated withCredentials: true (using XMLHttpRequest, credentials: include for Fetch)

We did a test implementation of this, and it seems to work quite nicely, but I still want to ask you guys as experts on this: Are there (additional) attack vectors when enabling this kind of refresh? In addition to the usual suspects for the implicit grant, that is.

Best regards, Martin

1 Answer 1

3

Instead of going with a completely different approach that as you mentioned would warrant a more thorough review from a security standpoint I would suggest leveraging what's already specified in OpenID Connect - the support of an immediate authentication mode through the use of prompt=none.

While SPAs cannot use refresh tokens, they can take advantage of other mechanics that provide the same function. A workaround to improve user experience is to use prompt=none when you invoke the /authorize endpoint. This will not display the login dialog or the consent dialog. In addition to that if you call /authorize from a hidden iframe and extract the new access token from the parent frame, then the user will not see the redirects happening.

(source: Auth0 - Which OAuth 2.0 flow should I use?; emphasis is mine)

Your authorization server will need to support this additional request parameter and also support auto-approval for requests/scopes that were already authorized by the user.

The main benefit of this approach is that it's leveraging most of what already existed so it does not significantly increase the attack surface as it would be the case for a completely new and different approach.

Check the Auth0.js library for a reference implementation in how this type of silent authentication could be accomplished.

1
  • This totally makes sense. And if I don't have a session on the Auth Server anymore, I'd return with an error message in the fragment, as per OAuth specification. Have to convince the frontend guys to have a look at hidden iframes. In the end, it will be more or less the same thing though: I rely on the Auth Server session.
    – donmartin
    Commented Dec 2, 2016 at 11:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .