AngularJS and authentication to an Oauth2 Provider? - ruby-on-rails

We have an API, Oauth2 Provider.
From AngularJS client Side app, how can I implement the flow of authentication to this api to get the access token for future requests?
What I am searching for is a Implicit Grant flow for this.
I'll provide a
{
client-id: "abcdefghijklmnopqrstuvqxyz0123456789",
redirect_url: "http:localhost:8080/provider_cb",
response_type: "token"
}
I have a Rails REST API in the backend and doorkeeper/devise for Oauth2 provision.
I came across angular-oauth, which seems to solve the problem to certain extent.
but,
I do not wish to provide a token verification function (Is this mandatory)
I do not wish to open a new window popup for the login (Wish to do redirections in same window)
Now,
Q1. What I do not understand is how is the whole process started, I can't make any $http request, this returns with a SignIn HTML page. Should I use $location service to redirect to it to login page? Or should I have a link to the whole GET request to /oauth/authorize?...
Q2, How will I capture the redirect after SignIn to extract out the access_token?
Q3. Do know any Service which takes care of Oauth2 authentication or a standard Angular way of doing this?

Lets try an answer to your three questions:
Q1) You should basically understand the general OAuth2 process. It is not an AngularJS-specific implementation you're looking at. If you don't want to work with a popup window for the authorization, you'll have to trick around a bit to have the redirect_url / state working correctly after coming back (if you want to have #state - saving - otherwise just specify your entry - url in the redirect_uri). You should not use $http for the redirection as this is just for XHR and similar calls useful. To get your user to the login page, just do a
$window.location.href = 'http://yourlogin.com/oauthloginpage';
Your app will then redirect to the login page - don't forget your parameters for redirect_url. Also specify other parameters within the request like "scope" / "state" if required.
Q2) The redirect AFTER Login will redirect to the uri you specified within your redirect_url. Then it will come up with something like http://myapp.com/#access_token=foobar&refresh_token=foobar2&state=loremipsem
Just grab the parts from angular with a bit of code like this:
var currentURL = $location.absUrl();
var paramPartOfURL = currentURL.slice(currentURL.indexOf('#') + 1);
Then parse the paramPart into an array with split('&') and iterate through it by looking for the "key" access_token and - voila - there is your access_token ready for being taken into your local storage / service / cookie.
There are other implementations you might use to split URLs into parts - maybe there is a better one, but this here would be the "fast shot".
After parsing, you can redirect the user again to the correct state with a normal $location.path(....) call and eliminate the # parameters of OAuth2.
Q3) If you want to have a way of mapping the source state / route of your AngularJS-app - try misusing the state parameter if your OAuth2-Server implements it. This will survive the request <-> response.
For a non-popup-implementation, I don't know any further module currently.
Another way to play with the OAuth2 stuff is to implement the loginpage on your own and then just interact with a oauth2 provider reacting on rest calls with Basic Auth or other methods. Then you can use $http calls probably.

Related

Best practice on Securing code_verifier in PKCE-enhanced Authorization Code Flow

Since PKCE is now the recommended method of authorisation over the implicit flow, i'm looking for best practice on handling code verifier and recommendations on how this might be done. On high level PKCE Authorisation flow consist of:
Generate code_verifier on client side
Generate code_challenge from (1)
hit /authorise with code_challenge which redirect to select idp and in callback there's a code
use code from (3) along with code_verifier to exchange for access token
Question is, in step 3, before the application redirect to authorisation server and then the idp, one has to store the code_verifier somewhere. Where is that somewhere?
Seems like libraries like okta-oidc-js store the code_verifier in sessionStorage. Doesn't that expose you to XSS attack? i.e. if i was store the code_verifier in sessionStorage before the application goes into the Authorisation flow and redirects, on the callback, what stops some rouge extension from reading the code from the url and code_verifier from sessionStorage? Combination of which can be used to exchange for a access token.
What you describe is the standard SPA way of doing things - it could potentially be abused by malicious code, but there is some protection in the fact that an authorization code can only be used once and that the verifier is not stored for long.
A related XSS attack is to run a complete OAuth authorization redirect + code exchange on a hidden iframe - there is no protection against that, regardless of whether a back end or client secret is involved.
If you want to be strict about security, the emerging trend is more of a back end for front end approach, where the back end is a 'Proxy API' running at https://api.mywebdomain.com
The result of OAuth authorization is a same site cookie issued by the API, to prevent the above iframe attack
The SPA can then either use the auth cookie to get an access token or double hop API requests via the proxy API.
There is a good recent video on SPA security here that discusses these threats in further depth. The browser is a difficult place to implement security and redirects come with risks.
It is still recommended to separate Web and API concerns however - eg the above proxy API should not get in the way of a company wanting to deploy their SPA via a content delivery network.
LOGIN DANCE
In my opinion the preferred approach is summarized below, for full control and no issues with recent browser changes:
SPA calls a URL such as https://api.mywebdomain.com/login/start, which writes an HTTP only encrypted cookie for .mywebdomain.com containing the state and code_verifier, and also returns the authorization request URL
SPA then does the redirect itself, and saves page location / state to session storage beforehand if needed
SPA then receives the response URL with code and state, then POSTs them to a URL such as https://api.mywebdomain.com/login/end. Afterwards the SPA can restore its page location and state, so that usability is good.
API completes the login by verifying the state against that in the state cookie, then using the code_verifier from the state cookie. The result of all of this is to write an auth cookie (containing a refresh token) that could not be abused on an iframe.
I agree with Gary's approach, with one change.
The response url with code and state does not need to be intercepted by SPA and converted into another POST call to the BFF (backend for frontend).
If secure cookies were set on the browser at the beginning of the flow containing state and code verifier, the response url can land directly on the BFF which will then have all the parameters available for performing the code exchange (state and code as url parameters, code_verifier from cookie)

Dropbox OAuth 2 dynamic return URL

The Dropbox OAuth 2 requires me to set a return URL. Is it possible to implement the OAuth 2 flow with a dynamic return URL?
Background on why I need the return_url to be dynamic: The flow works great if the integration is through a website, however I am working on a product which is managed through a web console, and typically users will access it using the private IP on the unit. This IP is something I cannot know in advance.
Possible Solutions if dynamic return URLs aren't possible:
I host a cloud service of some sort to act as a broker --- the broker is a fixed URL and I relay back the access code to the device.
Use OAuth 1, which doesn't seem to have this restriction.
Florent's comment is correct, this isn't currently possible, as all OAuth 2 redirect URIs are required to be pre-registered as a matter of security. I'll be sure to pass this along as feedback though.
As mentioned though, one thing you may be able to do instead is to use one static redirect URI but encode the necessary information in the 'state' parameter, and decode it as necessary after the redirect back to your app, to handle it as necessary:
https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize
Alternatively, you can use OAuth 1, which doesn't require pre-registered redirect URIs. Edit: note that OAuth 1 is only available for API v1, which is now deprecated.

How should I secure my SPA and Web.API?

I have to implement a web site (MVC4/Single Page Application + knockout + Web.API) and I've been reading tons of articles and forums but I still can't figure out about some points in security/authentication and the way to go forward when securing the login page and the Web.API.
The site will run totally under SSL. Once the user logs on the first time, he/she will get an email with a link to confirm the register process. Password and a “salt” value will be stored encrypted in database, with no possibility to get password decrypted back. The API will be used just for this application.
I have some questions that I need to answer before to go any further:
Which method will be the best for my application in terms of security: Basic/ SimpleMembership? Any other possibilities?
The object Principal/IPrincipal is to be used just with Basic Authentication?
As far as I know, if I use SimpleMembership, because of the use of cookies, is this not breaking the RESTful paradigm? So if I build a REST Web.API, shouldn't I avoid to use SimpleMembership?
I was checking ThinkTecture.IdentityModel, with tokens. Is this a type of authentication like Basic, or Forms, or Auth, or it's something that can be added to the other authentication types?
Thank you.
Most likely this question will be closed as too localized. Even then, I will put in a few pointers. This is not an answer, but the comments section would be too small for this.
What method and how you authenticate is totally up to your subsystem. There is no one way that will work the best for everyone. A SPA is no different that any other application. You still will be giving access to certain resources based on authentication. That could be APIs, with a custom Authorization attribute, could be a header value, token based, who knows! Whatever you think is best.
I suggest you read more on this to understand how this works.
Use of cookies in no way states that it breaks REST. You will find ton of articles on this specific item itself. Cookies will be passed with your request, just the way you pass any specific information that the server needs in order for it to give you data. If sending cookies breaks REST, then sending parameters to your API should break REST too!
Now, a very common approach (and by no means the ONE AND ALL approach), is the use of a token based system for SPA. The reason though many, the easiest to explain would be that, your services (Web API or whatever) could be hosted separately and your client is working as CORS client. In which case, you authenticate in whatever form you choose, create a secure token and send it back to the client and every resource that needs an authenticated user, is checked against the token. The token will be sent as part of your header with every request. No token would result in a simple 401 (Unauthorized) or a invalid token could result in a 403 (Forbidden).
No one says an SPA needs to be all static HTML, with data binding, it could as well be your MVC site returning partials being loaded (something I have done in the past). As far as working with just HTML and JS (Durandal specifically), there are ways to secure even the client app. Ultimately, lock down the data from the server and route the client to the login screen the moment you receive a 401/403.
If your concern is more in the terms of XSS or request forging, there are ways to prevent that even with just HTML and JS (though not as easy as dropping anti-forgery token with MVC).
My two cents.
If you do "direct" authentication - meaning you can validate the passwords directly - you can use Basic Authentication.
I wrote about it here:
http://leastprivilege.com/2013/04/22/web-api-security-basic-authentication-with-thinktecture-identitymodel-authenticationhandler/
In addition you can consider using session tokens to get rid of the password on the client:
http://leastprivilege.com/2012/06/19/session-token-support-for-asp-net-web-api/

ASP.NET MVC 3 Web API - Securing with token

I'm trying to find the simplest way of implementing token based authentication for a number of ASP.NET MVC actions.
The Api controllers sit alongside a web app, so I need to be able to specify which actions/controllers are subject to Api authentication.
I already have a membership provider that is used for forms authentication so I'd like to reuse this to validate the user and build the returned token.
I've read several articles on implementing OAuth, but most seem really complex. I've seen several examples of using an API key, but I want to request a token and then pass it back as a parameter not necessarily as a value in the HTTP header.
Essentially process needs to be:
User requests token from auth action passing in username and
password.
Service returns enc token
User passes enc token to future calls as a parameter to auth
What's the typical way this is done, does the client (say ajax call) need to compute a hash of the user name/pass in 1)? or plain text ok over TLS/SSL?
Any advice appreciated.
What are you concerned about with what you described?
The process you described seems viable. Typically systems will have an expiration on how long the token will be valid for, after which they need to get a new token. There are many variations for expiration though (fixed time, sliding time, etc..).
To your question regarding the username / password, the client shouldn't hash them. Just make sure they are transmitted via a secure method (SSL).

OAuth callback URL parameters with Doorkeeper

I'm Using OAuth2 with Doorkeeper to protect my API.
The problem is that one client had several different flows in which he redirects users to my OAuth flow.
He would like to dynamically add some parameters when redirecting the user to my OAuth flow and get these parameters back when I'm calling his callback URL. This way he will be able to tell from which flow this callback originated.
Is this possible with OAuth 2? with Doorkeeper? How?
Edit:
Thanks Zólyomi István for your hint.
I set the state parameter before calling the auth endpoint and got it back in the callback. However, I found that I get back a state parameter with some apparently random string even if I don't set anything. Any idea what it is? I'd like to be sure I'm not messing up anything...
Well, using the state parameter was indeed the solution. Just adding state to the request and then getting it back when the control is returned to my code.
According to the specification:
The state parameter is used to link requests and callbacks to prevent
CSRF attacks where an attacker authorizes access to his own resources
and then tricks a users into following a edirect with the attacker's
token.
Apparently ominauth oauth 2 assigns random value to this parameter unless it's used in order to detect CSRF attacks.

Resources