10

I am developing an application for my company with the following parameters & components:

  • 1st Party Frontend Single-Page Application (SPA). This is implemented in TypeScript (a dialect of JavaScript), and we are developing the code in-house.
  • 1st Party Backend REST API which gives access to a MongoDB sitting elsewhere. This is implemented in JavaScript and uses Express running on Node. We are developing the code in-house. Right now all this piece is doing is providing CRUD operations over a REST API.
  • These applications shall only be available to our employees. All employees have Windows 10 laptops which have been joined to our company's Azure AD.
  • We do not have an on-premise ADFS server. We are 100% cloud.
  • The application will use Azure resources in it's business logic, such as Graph API.
  • The application will also use other 3rd party resources, such as our company Dropbox.
  • Authenticating to "the application" should also authenticate against all other 3rd party applications (like Dropbox) as seamlessly as possible.
  • Today we have 10s of employees. It is highly unlikely we will have more than 50 employees in the next couple years, when this app will rev to version 2 and I will hire someone to build it.

The time has come to implement Authentication and Authorization for our application. The application should both Authenticate and Authorize against Azure AD. The ideal scenario is that a user logged in to the company laptop should be auto-magically authenticated on the application, and that users on another machine (think airport or hotel kiosk) would login using their Azure AD credentials.

My question is around which OAuth2 grant flow should be used in this scenario.

I have read a number of articles from Microsoft and OAuth, gone through a number of Udemy classes etc, and gotten conflicting advice from these sources. Some suggest that SPA's should use an implicit grant, while others say that if there is business logic on a backend server (and there is/will be) that a Client Credentials Grant should be used.

I'm a highly experienced developer, but I'm no security expert. In my perfect world I would outsource the design and implementation of the authentication piece of this app to someone who is a security expert, but budget is a major restriction here. It is simply not feasible to spend thousands of USD to have someone build this for us at this stage.

All this being said, given the design and architecture laid out above, how should authentication be implemented? Which grant flow should be used?

10

TL;DR Go with implicit... Check Which OAuth 2.0 flow should I use? for a visualization of the decision process.


When it comes to authentication, the devil is on the details... I'll try not to forget of any.

The base OAuth2 specification introduced four grant types:

  • implicit grant
  • authorization code grant
  • client credentials grant
  • resource owner password credentials (ROPC) grant

If you exclude ROPC which was included to provide a seamless migration path for applications that used to store the username and password in order to be able to act on behalf of the user, you're left with three possible grants.

Among these three, you make a clear distinction between the client credentials (CC) grant and the other two. The CC grant is aimed at client applications that want to access resources on behalf of themselves, that is, with the identity of the client application itself.

This implies that in order to use this grant a client application must be able to perform client authentication in order to prove that the request is coming from the legitimate application.

A SPA cannot perform client authentication because any secret, key that you store in the application as a means to authenticate would be visible to anyone that wanted to look through the source code. The CC grant is then restricted mostly to server-side applications where keeping a secret is easier.

Another major point is that if you want your client application to access resources owned by an end-user and/or perform actions on their behalf then the CC grant is not applicable.

It seems the pool of choices is now half of what we started with and the remaining candidates are the implicit or authorization code grant. In general, if you have a SPA the code performing the requests requiring authentication/authorization is on the browser-side so the obvious choice would be the implicit grant because it delivers the tokens as part of the authorization endpoint response and does not require an additional request to the token endpoint which in browser-land could signify a CORS request which might or might not be feasible.

As an additional note, if the components you described (Front-end SPA and Back-end API) are seen as a single application living under the same domain, with no plans on opening the API to other applications it should even be feasible to rely on traditional HTTP-only cookie-based authentication that would be bootstrapped by an ID Token received according to OpenID Connect rules. You mentioned REST so just want to make a disclaimer that cookie-based authentication does not necessarily imply a server-side managed session; however, cookie-based authentication would require CSRF mitigations.

  • Great answer. Thanks for the historical perspective. Your recommendation follows what Microsoft recommends as well, so that seems pretty clear. A couple quick follow-ups. 1) In order to implement implicit grant, I need to send my application's Client ID along with a GET request to MS. Is it safe to store that Client ID in my codebase, thereby making it visible in the application if someone chooses to look through my code? – John Dibling Dec 21 '16 at 14:26
  • 2) I noticed the article you linked to was published by Auth0. I've considered using that service instead of trying to do this myself, but in order to get all the functionality I need, it seems like it would be quite pricey. Is Auth0 a recommended service provider for this? Or is it just not worth it? – John Dibling Dec 21 '16 at 14:27
  • Regarding the inclusion of Client ID in the source code that is not an issue because OAuth2 does not consider this identifier to be confidential information; it's a way to know the source of the request so that any configuration associated with that client can then be respected. The part that you could not include in a SPA source code would be an OAuth2 client secret as that would be pointless as you mentioned. – João Angelo Dec 21 '16 at 14:33
  • In relation to Auth0, before saying anything else I need to disclose that I work there. If you considered it, the best advice that I can give you is that you should have a go with the free trial and then compare the costs of acquisition of the service versus the cost of owning a custom solution or a solution with another provider. In terms of features it does seem a good match, it integrates with Azure AD and also offers SSO integrations with many apps, including Dropbox. – João Angelo Dec 21 '16 at 14:40
  • 1
    @bitgandtter you're correct that the client identifier is not enough to provide client authentication, however, with the implicit grant you will also need to provide a redirection URI that the authorization server will validated to ensure it's in the list of allowed URI's. This validation means that although anyone can initiate the request, the response will only be delivered to a whitelisted URI which helps avoiding the situation you describe of a rogue application obtaining a response. This of course implies that all the whitelisted URI's are under you control. – João Angelo Sep 27 '17 at 13:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.