Consuming my own Public API on my website - oauth-2.0

I have a website that exposes a public API. I want to secure this public API using OAuth 2. In order to minimize the number of code paths to maintain, I want to refactor my website to use the OAuth 2-secured public API endpoints.
The way I intend to do this is to register an OAuth 2 Client in my server as "my website", and then have that fetch a short-lived token. I see 2 problems with this approach:
My client would have to effectively have every scope, since the
website encompasses every possible action. The API is just a subset
of this (though I'm hoping to change that). The second issue is
security and caching of the token. The token would live for an hour.
If the user refreshes the page, do I fetch another token? If I store
it locally in a cookie or localStorage, is there a security
vulnerable of some sort?
Let's say I register a different OAuth Client for each page of my UI. The would make it so that the token in #2 would have limited scope if stolen, but it gets extremely tedious.
The alternative is to not use the public API on my website, and protection relies on CORS. Malicious attackers cannot access these endpoints because they are only allowed to come from the domain the user is on (and things like nonces).

Sounds like you want towards a model based on a Browser UI calling APIs directly, which is certainly the most attractive architecturally.
This may be the first step to a Single Page App architecture, which tends to provide the simplest and cleanest solution.
See Open Id Connect for browser apps for latest standards.
In an SPA the UI is cookieless and it is common to store short lived access tokens in HTML5 session storage, which means the user can refresh the page ok
It is true that all scopes are retrieved after login, but if you keep scopes simple and authorize in your API based on user rights you can mitigate that
The above token storage is the default behaviour for the certified OIDC Client Library and widely used.
There is a cross site scripting risk, that malicious content in your browser tab can get a token and call the API - but you should be protecting against this anyway.
Older solutions such as use of auth cookies tend to have their own (and bigger) risks such as cross site request forgery, where any malicious content in any browser tab can send the cookie to your API.
Evaluating whether to use HTML5 storage of tokens is about more than just the technical mechanism - it is about acceptable trade offs around usability and what can be done with the token. My blog post on UI token storage drills into this.
If it helps, my blog also has quite a few posts and code samples on SPAs, in case it is of interest.

Related

How can I restrict access to my rest API?

I'm developing my very first mobile application and I need advice. I created REST API in spring boot and it works great but I want to restrict access. It should be used only by my app. There is no user login it only gets data from the server.
Would be some API token enough or is there any other way how can I do this?
maybe it's a stupid question but I really need advice.
thanks
You can use these pointers -
Least Privilege:
An entity should only have the required set of permissions to perform the actions for which they are authorized, and no more. Permissions can be added as needed and should be revoked when no longer in use.
Fail-Safe Defaults:
A user’s default access level to any resource in the system should be “denied” unless they’ve been granted a “permit” explicitly.
Economy of Mechanism:
The design should be as simple as possible. All the component interfaces and the interactions between them should be simple enough to understand.
Complete Mediation:
A system should validate access rights to all its resources to ensure that they’re allowed and should not rely on the cached permission matrix. If the access level to a given resource is being revoked, but that isn’t reflected in the permission matrix, it would violate the security.
Open Design:
This principle highlights the importance of building a system in an open manner—with no secret, confidential algorithms.
Separation of Privilege:
Granting permissions to an entity should not be purely based on a single condition, a combination of conditions based on the type of resource is a better idea.
Least Common Mechanism:
It concerns the risk of sharing state among different components. If one can corrupt the shared state, it can then corrupt all the other components that depend on it.
Psychological Acceptability:
It states that security mechanisms should not make the resource more difficult to access than if the security mechanisms were not present. In short, security should not make worse the user experience.
Always Use HTTPS (This is hard)
By always using SSL, the authentication credentials can be simplified to a randomly generated access token that is delivered in the username field of HTTP Basic Auth. It’s relatively simple to use, and you get a lot of security features for free.
If you use HTTP 2, to improve performance – you can even send multiple requests over a single connection, that way you avoid the complete TCP and SSL handshake overhead on later requests.
Use Password Hash
Passwords must always be hashed to protect the system (or minimize the damage) even if it is compromised in some hacking attempts. There are many such hashing algorithms which can prove really effective for password security e.g. PBKDF2, bcrypt and scrypt algorithms.
Never expose information on URLs
Usernames, passwords, session tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them easily exploitable.
https://api.domain.com/user-management/users/{id}/someAction?apiKey=abcd123456789 //Very BAD !!
The above URL exposes the API key. So, never use this form of security.
Consider OAuth
Though basic auth is good enough for most of the APIs and if implemented correctly, it’s secure as well – yet you may want to consider OAuth as well. The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.
Consider Adding Timestamp in Request
Along with other request parameters, you may add a request timestamp as an HTTP custom header in API requests. The server will compare the current timestamp to the request timestamp and only accepts the request if it is within a reasonable timeframe (1-2 minutes, perhaps).
This will prevent very basic replay attacks from people who are trying to brute force your system without changing this timestamp.
Input Parameter Validation
Validate request parameters on the very first step, before it reaches to application logic. Put strong validation checks and reject the request immediately if validation fails. In API response, send relevant error messages and examples of correct input format to improve user experience.
You can use this as a checklist while making a rest API

How to handle authorization and authentication on SPA with OAuth2?

I am developing an SPA and would like to have SSO.
As I understood so far, OAuth2 with OIDC is the best solution for SPA SSO.
Better than, for example, SAML.
What I didn't understand so far is how to use authorization token in SPA's JS code to handle authorization on various resources of SPA. For example, I would like the users with a role 'buyer' to have access to the shopping history tab, where other users won't have access to.
Should I parse access token obtained from Authorization server in JS code and check whether a user has an appropriate role to see the tab, or should this decision be made on server (API) side, in which case SPA's code would just read the answer from API and based on that customize UI?
In case of the first approach, is there any standard way of doing the checking (in form of some JS library)?
When it comes to authentication, what is the better approach (more secure, etc):
to let SPA (at that point already loaded in the browser) do the authentication flow and based on result let the user use it's protected functionalities. This is pseudo authentication actually since the code is in the user's browser and means the user is authenticating himself to the code in his hands i.e. to himself. Does this authentication make sense at all?
require the user to authenticate himself in order to be able to even load the SPA in his browser. This is probably not SPA architecture then since backend which serves the SPA should be able to create a backchannel with the Authentication server.
According to user description, your application must vary depending on user type. If this is the case I would suggest you to use a backend for authentication and decide application content to be served from the backend. Otherwise, as you have figured out, running authentication on browser and altering user view is not secure.
IMO this not necessarily break SPA architecture. What you are doing is altering what you server based on tokens presented to you. Also, maintaining a session will be required with this approach. And SPA's calls for backend will require to contain this session to obtain contents.
As soon as the User is logged in, you would request for authentication and based on his UserId, and the role he belongs to you should receive all the permissions that User is entitled to.
You convert these permissions into claims and can send them back to UI and use it appropriately to show the features accordingly.
You also enforce same on the server side api to prevent any unauthorized access besides from your UI.

Token vs Cookie for SPA

I'm using devise_token_auth for a rails application with react on the frontend and rails as the backend acting as the backend.
In the readme the author states that
If you're building SPA or a mobile app, and you want authentication,
you need tokens, not cookies.`
Why? I understand the basic differences between tokens and cookies, but don't understand why you couldn't just use cookies (simply including the headers with any XHR requests)?
There are a few major reasons.
First of all most SPA's are designed as stateless and using cookie based authentication is not stateless. Using cookies also makes every request take a little bit longer because there is a lookup on every request.
Cookies are also tied to a domain. Most SPA's use multiple services across multiple domains which is a no go with cookie based authentication. This also applies to SPA's which have a web app and mobile app, using token based authentication means scaling this is much easier.
Tokens can also be used to store data and only need to be generated once, after that there is no work involved except for the server reading the token. This means you can store user permissions in there etc and the server can get this information with very little work.

Browser applications and auth tokens again

I've been reviewing how we should handle OAuth authentication in our browser application (SPA), and there's a whole bunch of articles out there that makes it all really confusing... I'm really missing something concrete and best practice guidance for a very simple setup.
We have this ASP.NET Web API 2 that's protected using tokens issued by IdSvr3. So far so good. Works with native clients and server apps.
Now to the browser stuff... Looking at a sample such as JavaScriptImplicitClient which uses the oidc-client-js library to retrieve tokens using the implicit flow. The token is stored in the browser which is accessible using JavaScript and there by open to XSS attacks.
In order to avoid that, suggestions indicates storing the token in a cookie and then setup a mechanism to prevent CSRF attacks.
Seems simple, but what sets that cookie?
Is it the IdSvr? Doesn't make sense since it's the API that needs the cookie.
Is it the API? During Implicit Flow login, are the user then redirected to the API which sets up the session and then redirects the user back to the SPA with a Set-Cookie header? Then the cookie will be present to the API on subsequent requests.
Third solution? Some is mentioning creating a second 'API' that proxies requests to the 'real' API, but sets the auth header.
Do you have any samples of such a setup, or can you maybe provide some hints about how you'd do it?
Personally, most of the times the avoidance of Web Storage for tokens due to XSS seems to be exacerbated a bit. There is one important question, if your application is vulnerable to XSS, will the impact of this vulnerability be significantly increased because you also leaked tokens or you already got totally pwned even if you didn't store tokens there and you're in the same type of trouble.
I made a comparison of the pros and cons of a few approaches to store access tokens in web browser application which you can check in this answer to a related question.
In the end each case ends up having their own specifics which may tip the balance between one approach versus the other (cookies or web storage). Just don't ignore any option from the start and look at all of them based on your requirements.
I bet that there are implementations out there that store them in HTTP-Only cookies to avoid the XSS issue with Web Storage and then end-up using a CSRF mitigation strategy that is vulnerable in the face of XSS.

Sharing AccessToken to clients (say browser) is a security concern?

We have a MVC application, in which we are making web api calls from browser to get the data and display it in browser. Since our application is Claims aware, the client need to pass AccessToken in order to access the web api.
Since the browser is not a trusted client (server does not have much control over browser), is it advisable for clients (browser) to store AccessToken? are there any better design patterns here without compromising security?
You'll have to trust the browser to some degree, otherwise your web application won't be of much use. Before tokens and API's, traditional server-side applications trusted that session identifiers could be stored by the browsers in cookies.
With tokens, the principle is the same, but the devil is on the details. First of all, assume HTTPS needs to be used, otherwise you might as well give up. Having HTTPS in-place, you can assume to some extent that sending the access token and/or cookies to the browser is secure.
After that, you need to worry about the characteristics of the storage the browser will use. For that I would recommend to read the Where to Store Tokens? section of the Cookies vs Tokens: The Definitive Guide article.
The real problem is that there are a sufficient number of other small details that is almost impossible to provide a definitive list and even though they are small details they can have very big impact on the overall security of the system. The only honest recommendation is that if you want to roll your own authentication system you need to be prepared so spend significant time and resources learning all these details.

Resources