Using OAuth2 for securing a monolith private REST api? [closed] - rest

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Maybe this question seems opinion based, but I am facing a hard time in deciding to secure a RESTful API.
Firstly, my use-case:
My application is pretty straight forward: The front-end is written using React.js(for browser client) and that will consume the RESTful API for getting its data from the database(or something). The API is built using Spring framework.
This API is not a public API, and it has only a single client(as of now, later would be mobile apps).
Now lets come to the security problem. Obviously, I want to secure my API, I am using Spring-security as a tool for this job. During the starting days of learning, I knew only about the Basic-Authentication. But, when I kept on reading about more secure options, I learned some new fancy terms:
Token-based Authentication, using JWT
OAuth2
OpendId connect
When I read more blogs like from Auth0, Okta and a lot more, I messed up everything. This made me think twice if I should use OAuth for securing a REST API (which is not public). Also, almost all of the blogs about OAuth take examples of social logins. This made me more messed, that OAuth is for giving access of your API to the third party application. And that's it, not for my use-case.
I then asked some experts from some channels and blogs, some said the Basic-Authentication is very enough for security(using https) and I should avoid OAuth for such a small requirement. Other said opposite to that, saying Basic-Auth has security vulnerabilities.
Let's consider that OAuth is perfect for me, but in that case also, where would my Authorization server reside? Because tutorials only explain about Authorization server by keeping their code in the same layer. No separate project or something.
JWT also has some negative reviews for my user-case:
they cannot be revoked, will only expire on its own. Isn't it insecure?
they are massive in size, compared to session token or cookie
hight computational cost for verification
I really need some more advice on this, it has already taken my lot of weeks.
Thanks.

The real answer depends on information not in your question. For example do you need identity verification or are you just authorizing API access?
OAuth and Open ID Connect (OIDC) today are basically the same thing for most services such as Google Login. OIDC adds an identity layer on top of authorization. If you need to verify the identity of your users, log their activity, control resources per user, etc. this is your solution.
For authorizing API endpoints, there are many solutions. The most common are secret key value and JWT. Secret key has many weaknesses so I will not touch on that here.
A very common method of authorizing API endpoints is using JWT tokens and the Authorization: Bearer TOKEN HTTP header. I will now try to answer your concerns about using JWT tokens. Here I only refer to Signed-JWT tokens.
they cannot be revoked, will only expire on its own. Isn't it
insecure?
JWT tokens can be revoked by revoking the signing certificate. This would require creating a certificate revocation server, so this is not so common. An improved approach is to create short-lived tokens. Typical expiration time is 60 minutes (3600 seconds) but you can create tokens for any time period. When the token expires, the client requests a new one, which your backend can authorize or refuse.
they are massive in size, compared to session token or cookie
What is massive? You can create a token of any size from just a few bytes (the size of the signature plus data) or include extensive information in the token. Unless your tokens are out of control in size, this will not matter to most implementations.
high computational cost for verification
Again you are using a vague term. Verifying a Signed JWT is not computational expensive unless you are on tiny devices such as IoT (which are already using SSL certificates, encryption, etc.) or you need to handle millions of transactions per minute. In other words unless you have a solid reason to worry about CPU cycles, don't worry about them in regards to improved security.
Let's consider that OAuth is perfect for me, but in that case also,
where would my Authorization server reside?
Your OAuth 2.0 authorization server can reside anywhere you want. Implementing OAuth is very easy and there are many libraries to manage the details for you. Your authorization server can be part of your backend, be a separate server, etc. You can even just outsource this completely to identity providers such as Google Login, Auth0, Okta, etc.

Related

JWT / Session Cookie Authentication Hybrid

I'm looking for some clarity regarding security concerns with just JWT in our current project.
basically it is working right now like this:
User authenticates with username + password at an authentication Service
frontend gets JWT
frontend can use this JWT in the communication with the backend.
but that seems unsecure for many reasons, so we discussed this so far and had a few ideas to make it more secure:
additionally encrypt the JWT, basically make an nested JWT (JWE) and work with a blacklist on logout... but here the question remains why work with an JWT and not a stateful authentication like Shared Sessions and a Redis service
Implementing an Api-Gateway so that the frontend or User gets a Session cookie and the gateway works with JWT for backend and auth. unfortunatly i've found no implementation like this whatsoever
We just want to be kinda secure in Login/Logout AND be scaleable in the the future so that there might be X other backends.
apologies for any errors, english is not my first language and i'm happy to answer any questions regarding this.
take care.
You are right that keeping tokens on the front end has some security issues. The current best practice is to try to keep tokens out of the browser altogether. At Curity we have described one possible solution as the Token Handler pattern. It adds a bit more complexity to your system but enables you to use secure sessions on the front instead of any tokens. We have provided a few implementations of the components needed by the Token Handler, you can have a look at how to run our complete example here: https://curity.io/resources/learn/token-handler-spa-example/
As to your first idea, if you want to implement blacklisting tokens, then you're in fact implementing sessions, and you're better off with cookies and plain old HTTP sessions. JWEs protect the contents of your token but an attacker can still steal such a token and use it to call your APIs.

Restrict REST API access to only registered site

I have an old question that maybe is asked here many times, but still we are in 2022 maybe there is some better approach to solve this problem.
I have an API that is used by some websites (clients) that is registered in this API, Those clients use this API to display the list of services for private and public users without any authentication.
When the client registered in the API a personal access token is given to send it for each request before using the API to limit abuse of this API.
The problem with an access token in public side, is anyone can intercept it and use it outside of the site generated for wish will cause a lot of cost.
Even if I reduce the lifetime of token to 10 min I still have the risque of abusing with it.
Is there any way to better secure this API other than authenticate the client for each request to get the fresh token with a lifetime in seconds?
To better illustrate the question above this is the use case:
The malicious user connects to the first registered site as the site list the services to the public users, the malicious user intercept the token in the header to the API
The malicious user come to his unregistered site and use the token
All this step can be automatised by the malicious user.
Edit:
I cannot change the client implementation or ask him for any change, I search something to reduce abuse not at 100 % but to make abuse a little complicated, like using origine domaine name, CORS, ...
The vast majority of access tokens used today are bearer tokens. This means that the resource server will accept the token if it is valid, and doesn't care about who has sent that token. You are right, this means that a malicious user can steal your token and use it to call your API. There are more ways for an attacker to steal access tokens, not only MITM attacks (which, as noted in the question's comments are pretty much mitigated by using TLS). You can have XSS attacks if the tokens are made available to a Javascript app, or Man-in-the-Browser attacks, where the token is stolen by a malicious code running in the browser.
These attacks are usually mitigated by using short-lived access tokens (even less than 10 min) and putting rate-limiting in place. This usually is enough to prevent abuse. You can always add additional layers of protection, e.g. drop a token if the caller's IP changes, etc.
If you need stronger protection, then you can have a look at sender-constrained access tokens. These are tokens, that can be used only by the legitimate client. Sending such a token requires the client to present additional proof of possession. This is then verified together with the token itself.
There are different possibilities for implementing sender-constrained tokens, e.g. Certificate-bound tokens or DPoP.

General API security tips and info on how tokens work

So I want to understand a little more about authentication in an API. I know very little about how security works.
I am using Auth0 for my app and it supports only logging in from a social media site. My API checks if a user is authenticated and checks data that is being sent to avoid wrong stuff to be saved in the database(mongodb). That is all I have currently implemented to secure my API. Is it possible that a user can take his own token that he got from logging in and post information to a different account by simply guessing a different user _id.
For example, an article receives all its content and the id of the article author.
If this is possible what are some solutions on securing my API.
Any other tips on making an API secure are appreciated!
Auth0 supports logins with anything , not just social networks. You can login with username/passwords, LDAP servers, SAML servers, etc.
A token is a secure artifact. An author cannot change the id in a token without compromising the token itself (e.g. the digital signature will fail), so impersonating someone else is not that easy. The very first thing your API would need to do is checking the integrity of the token being added to the request, and reject any that contains an invalid one (bad signature, expired, etc).
It is a question that requires a lot of content, so I would recommend starting here: https://auth0.com/docs/api-auth

Authentication with Akka-Http

We're developing an iOS app, where the user needs to authenticate using email+password (or mobile number). Our backend is made of a couple of microservices using Akka-Http. It needs to be fast, scalable, concurrent, and the authentication+authorization should work across our multiple services.
I'm trying to figure out which authentication method to use.
Akka-HTTP currently offers Basic Auth and a partial implementation of OAuth2.
So at first we were considering Basic authentication (too simple and not enough functionality), Oauth1 (too complex), so we moved towards OAuth-2.0 because it is sort of a standard.
Then we considered AWS Cognito because it combines Oauth-2.0 and OpenID Connect which gives the authentication mechanism that OAuth2 lacks.
http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html
Then we realised that OAuth2 is just for authentication using a third party - when in fact we don't need a third party authentication provider - maybe we need to do it ourselves, and using Cognito is an overkill that would create extra api calls outside our microservices...
So I read a little bit about creating our own custom auth provider, using WSSE specs:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
And I also found this example using Spray, but I'm sure it's not that different from Akka-Http:
http://danielasfregola.com/2015/06/29/how-to-create-a-spray-custom-authenticator/
It looks too simplified and doesn't have token expiration...
So my question is, am I missing something? What method should I chose and where can I find examples for it?
I feel like I'm going in circles, we're gonna have to write our own custom authentication provider from scratch, which kinda doesn't make sense. After all almost everybody needs authentication and it should be a standard.
I've recently been using SoftwareMill's akka-http-session library and found it simple and easy to integrate. It has support for case class based sessions, JWTs, refresh tokens with pluggable storage, using headers and CSRF tokens as well as some nice simple directives for use in routes.
My solution for user registration has been to use Keycloak, an open source server which can handle user registration and do OIDC, OAuth2 style login. It reduces the amount of code I have to write, and the code is more secure than if it rolled it myself.
I then write my application as Scala backend that's purely a JSON API and a React/Javascript rich frontend in front of that API. In this configuration the authentication is handled completely on the front-end (and can be done in your iOS client). The front-end app redirects the user to Keycloak and when the user comes back they have a signed "JWT" token you can keep in a cookie.
That JWT token is attached to all API calls made the JSON backend as an Authorization Bearer token HTTP header. The token itself contains the users email address and is cryptographically signed by the Keycloak server.
The backend gets the JWT token in the HTTP header, extracts the email address and verifies the token is cryptographically signed by the keycloak server.
It's performing a certificate check on the keycloak server and can cache it's certificate. So it doesn't need to have roundtrips like OAuth, or any upstream calls to make.
This gives us simple, low-chance-of-failure, high speed authorisation in our JSON backend API and means we aren't putting secrets in the iOS client, or rolling too much of our own code.

How do I implement authentication the restful way?

I'm building a picture diary on web application google app engine using python. Users can sign up and post pictures to their diary.
Also, I'm trying to conform as much as I can to the REST architecture of doing things.
The authentication scheme is based like this for the web application:
1. Post username/password from the frontend
2. Backend sets up a cookie if authentication is successful
3. The rest of the AJAX calls made are authenticated using this cookie.
Is there any way to conform to REST without using cookies ?
Now, I'm also building an android application where users can sign in and post/view their picture diary. I need to expose the data from web application's datastore so I'll be building a webservice to fetch data from the datastore.
The authentication scheme for the android client:
OPTION a
1. Post username/password over https to the web service
2. Web service returns a unique authorization token (store the token in the username/pwd table on the datastore)
3. Request subsequent services by adding this token to the Request Header of the request
4. Server maps the token to the username/pwd table and returns data if token is found
5. Authorization token expires after a certain period of time
OPTION b
1. Set up a secret key on the client and server side
2. Use "username:hash of password and secret key" in the authorization header of every request
3. server generates the password by extracting the password from the hash value using the same hash algorithm ; if successful returns data
btw, I didn't wanna use basic authorization because of its security vulnerabilities.
Which is better ?
Are there other significantly better ways to accomplish what I'm trying to do ? Security is quite a concern for me btw.
I'd appreciate if anyone has any insight into this issue. thanks.
I've been doing some research myself as to what would be the best solution. I think the 2-legged oauth might work in my case as Leonm suggested.
In this case the server has to provide the client with a consumer key/secret which in my case is hardcoded in the app.
The steps now would be:
1. Generate a signature using the oauth_parameters(consumer_key, signature_method, timestamp), request url, request parameters, and the SECRET.
2. Include the signature, oauth parameters when making a request.
3. Server verifies the request by generating the signature again except in this case it uses the SECRET that corresponds to the key
I think this way I am pretty much confirming to the REST principles. The server is statless as I far I understand now.
What are the pros/cons on doing things this way?
If "security is a concern" then I would say that you'd be a lot better off using open standards and a library to achieve what you want. The main reason for this is that if you do it yourself, you're very likely to forget something; these standards have had a lot of eyes looking at them, looking for holes.
Your options include (in increasing level of complexity)
Basic authentication and HTTPS
Everything is encrypted, which makes it impossible to compress or look into, it increases the overhead somewhat, using more horsepower on the server, and more perhaps battery power on the client. Simple to implement, since it's well supported by libraries.
Digest authentication
Unencrypted messages pass the wire, but the authentication is securely managed in the Authorization headers. See the wikipedia entry for more information.
OAuth
See how Google is providing OAuth for installed applications. I believe it isn't what you're looking for, since you're not asking to share data between applications, just authenticating users.
Roll your own
If you want to roll your own, I suggest looking at e.g. how Google's (now deprecated ?) ClientLogin used to work.
Clients would GET a protected resource, and get a 401 with instructions to perform a GoogleLogin authentication, including a URI for where to perform the login itself
Clients (knowing how to do this) POST a request in a specific manner to that URI
The server responds with a specific response including a (long) token
The client can now perform GET requests to the protected resource with that token.
Statelessness
You cite REST, which dictates that requests should not specifically depend on prior interaction: "... each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server." (fielding) This means that a server shouldn't store conversational context (like an authentication token) in a table.
One way of fixing this is by using any of the token based approaches (where the server tells the client about a token it should use for future requests) where the token is not a random number, but a message to the server itself. To protect yourself from client tampering, it can be signed, and if you're afraid of clients looking at it, you can encrypt it.
Edit: Although I'm not certain, it seems unlikely that Google has a table of all authentication tokens ever issued; The length of their tokens suggests that the token is some encrypted message proving that whoever holds this token actually provided real credentials in some realm at some time.
OAuth does exactly what you want to do in a standard way.
You could use a combination of HTTPS and HTTP Basic Auth. Both are existing standards and should be secure enough when used together.