does adal.js support Authorization Code Grant Flow? - javascript

For a while now I had a .Net WPF application that uses Adal.Net to perform (what i believe is) an Authorization code grant flow against azure active directory to access a web API (which is looking for a bearer token in the request).
For this purpose I'm using 2 AAD applications: MyServer (which represents the server) and MyClient (which represents the WPF client). In the azure portal I configued Myclient with permission to access MyServer.
When calling AcquireToken from my WPF application i'm supplying MyClient.ClientId as the client ID and MyServer.ResourceUrl as the resource id, and everything works as expected.
Now I have a website (that only serves static pages using IIS - it does not have asp.net nor node.js as web servers).
I would like to my browser to perform the same flow the .Net native app performed.
I've looked at adal.js but wasn't able to find an easy way to do it.
Must I implement the entire flow by hand?

Rony, AAD doesn't support cross origin calls on the token endpoint - so you won't be able to implement the auth code grant OAuth flow in JS (the token request using the code will fail). AAD supports the implicit grant OAuth flow for the scenario you describe (single page app calling a web api).
ADAL.js implements the implicit grant flow. Please let us know if you have any issues using it.
Hope that helps.

Related

Why isn't clientID enough for using Google APIs?

From Google's API explorer and using Authorize requests using OAuth 2.0 as I want to on my SPA, I see a YOUR_API_KEY is somehow derived from a login and used in subsequent calls to:
https://www.googleapis.com/youtube/v3/channels?part=statistics&id=UCE5Au4LfcBHxTQR_yLbncrQ&key={YOUR_API_KEY}
How do I get this key? I am working from GAPI.auth2.getAuthInstance() in a VueJS app.
I can see gapi being used in Google samples. But I just want to do simple direct fetch calls with this user's API key for the session. I do not want to use gapi.client, or do I have no choice?
Update: On the Oauth2 playground I see it refers to a client secret 1. I don't understand this at all, since with a SPA with no backend, you don't want to store a secret! Why isn't the client ID and the origin enough?
Here's another confusing example (no secret used) where the apiKey is used together with the clientId. Why isn't clientId enough, since it's restricted by origin?!
Generally, there are 2 types of OAuth flows to obtain an access_token when on the web. One is called implicit flow and other is called authorization code flow.
For the code flow, you would require the client_secret in order to exchange a code with an access_token. This usually happens on server side.
For the implicit flow, you can simply give a client_id to obtain an access_token and it is designed to work on client side.
The screenshot you've attached is the OAuth flow part where you exchange an auth code with an access_token. Because the playground is using the authorization code flow.
What you are looking for should be the implicit flow.
To achieve this in YouTube client library (or whatever Google javascript client lib), you don't need a client_secret. You can find a complete example using Google Drive here:
https://github.com/GoogleChrome/google-sign-in/blob/master/static/scripts/authorization_client.js

IdentityServer3 - OAuth Flows, different approaches

I've built an application that is substantially a REST Web API. I would like to give to other developers the opportunity to invoke those APIs on behalf of the user. I decided to go on with OAuth authentication, basing my Authentication Service on IdentityServer3.
Right now I've succeeded in generating an Access Token for a third-party client using Authorization Flow.
What is not convincing me is how to handle my SPA that currently invokes my Web API using just cookie based authentication (+ anti-forgery token). This application in written in Javascript, based on Backbone. Substantially, what it does is just call my Web API and render results. I'm confused by the different grant flows, and I don't want to create security holes.
Solutions I've thought:
generate a token directly via Javascript. Which kind of flow should I use? How to handle token refresh?
generate a token from a backend server application and pass the generated token back to the SPA (obviously through an SSL channel). Is this somehow secure? If yes, which kind of flow should I use (I'd say Authorization Code Flow)? How to handle token refresh?
How would you handle this?
Thanks,
Marco
Here's an article that goes into an overview of which flow is right for which scenario: https://leastprivilege.com/2016/01/17/which-openid-connectoauth-2-o-flow-is-the-right-one/

Authenticating with ADAL JS not behaving as expected

I have two Azure AD applications in the same directory, let’s call them FrontendAuth and BackendAuth, which provide authentication for an ASP.NET MVC frontend and a Web API backend, respectively. The MVC frontend is protected using the standard UseOpenIdConnectAuthentication configuration, the Web API backend with UseWindowsAzureActiveDirectoryBearerAuthentication.
What I want to do is log into the frontend, authenticate against FrontendAuth, then consume via JavaScript the API hosted in the backend by providing a token, acquired using ADAL JS, to BackendAuth.
Assumptions
My expectations/assumptions are:
That I would have to configure FrontendAuth to have access to BackendAuth in the classic portal
That I would have to edit the manifest files of one or both of these to set oauth2AllowImplicitFlow to true
That when I configure ADAL JS I should be setting clientId to be that of FrontendAuth
The endpoints object of the ADAL JS configuration should contain the Url of the backend API and the client ID of BackendAuth
Outcome
I can achieve my goal of logging in to the frontend and communicating with the backend service via ADAL JS with:
The FrontendAuth application having no access to BackendAuth at all
Neither manifest file having the oauth2AllowImplicitFlow property set to true
ADAL JS having the clientId set to be that of BackendAuth
The endpoints object of the ADAL JS configuration not set at all
Questions
Based on these findings I would like to understand the following:
Were my assumptions correct? Is this how ADAL JS is intended to work?
Why did the lack of application access and unchanged manifest files have no effect on whether the authentication succeeded?
When do these measures have an effect on the authentication outcome?
You are mixing up two OAuth2 flows here (authorization code flow and implicit flow). Both are meant to issue a token to a client application. The auth code flow is used for web apps running on the server (like your MVC app) and the implicit flow is meant for public clients like a SPA.
When you use OpenID Connect to sign in your user to your MVC application, using the hybrid flow, you receive an authorization code from the browser. You use this code to talk to the authorization server and get a JWT token which is then stored in a cookie session. You can use the same code to get a JWT token for your BackendAuth app, as long as you have given permission to your FrontendAuth app to call the BackendAuth app.
If you want to enable the JavaScript in the user's browser to call into the BackendAuth app, you'll need to somehow pass the access token to the browser. You can do this by sending the token along with the initial request and put it in local storage or expose a (secured) MVC route to get the token.
For an example of what I'm describing here see this Azure AD sample, which acquires a token for the Graph API using the authorization code is received.
ADAL.js implements the implicit flow and is meant for JavaScript applications like SPAs etc.
It sounds like you haven't explicitly decorated your Web API controllers with [Authorize] attributes (either at the class level, or the action level). Thus, your Web API may be happy to serve content to anyone who requests it.

authentication using Doorkeeper from client-side application without transmitting secrets

I'm trying to use Doorkeeper in a Ruby on Rails API app for authentication. From a client-side AngularJS app, I want to get an access token. Currently, this involves a GET request to /oauth/authorize, which gives me a code, then I POST that code along with a client_id and a secret to /oauth/token. I don't want to have to send the client ID and secret from my client-side app, since they're stored in plain-text in a JavaScript file. I would like to follow this flow where response_type is token, not code, but I can't figure out how to do that with Doorkeeper. Their wiki examples all seem to involve POSTing the client ID and secret to /oauth/token.
Is Doorkeeper the right gem for this? How can I do Google OAuth2 from a client-side app, where no secrets are passed from client-side to the server?
Edit: looks like what I want is Implicit Grant, which Doorkeeper supports. Now I just have to find out how to do that in my Rails app...
No extra server-side configuration necessary.
When I created a new Doorkeeper::Application in my Rails app, the Doorkeeper interface gave me an Authorize link with response_type=code in it for that application.
I changed that to response_type=token and when I do a GET request to that, it responds immediately with access_token instead of code. The Authorize URL looks like http://my-rails-doorkeeper-app/oauth/authorize?client_id=1234&redirect_uri=http://my-angularjs-app&response_type=token.
Update :
This can only be applied when we also allow implicit grant for the grant flow.
By default, doorkeeper will allow its four kinds of flow (implicit grant, authorization grant, password, and client_credentials).
You can configure it in initializer/doorkeeper.rb if you don't want to let it happens since sometimes it can be dangerous.

How to protect a private REST API in an AJAX app

I know that there are many similar questions posted, but none of them refers to an HTML/javascript app where the user can access the code.
I have a private REST API written in nodejs. It is private because its only purpose is to server my HTML5 clients apps (Chrome app and Adobe Air app). So an API key is not a good solution since any user can see the javascript code.
I want to avoid bots creating accounts on my server and consuming my resources.
Is there any way to acomplish this?
An API key is a decent solution especially if you require constraints on the API key's request origin; consider that you should only accept an API key if the originating web request comes from an authorized source, such as your private domain. If a web request comes from an unauthorized domain, you could simply deny processing the request.
You can improve the security of this mechanism by utilizing a specialized encoding scheme, such as a hash-based message authentication code (HMAC). The following resource explains this mechanism clearly:
http://cloud.dzone.com/news/using-api-keys-effectively
What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. If you're using Android, you can use the keytool included with the Android SDK for this purpose; if you're using another app platform, similar tools exist for them as well. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.
A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in Android (I'm not as familiar with how to do this on other mobile platforms), both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.

Categories

Resources