I have a set of REST APIs that are secured by oauth 2. I need to access them from an Android app and a webapp.
Accessing the APIs from android app seems pretty straight forward for me to implement. What I am unable to understand here is - what is the correct and secure way to access the same APIs from a webapp?
I am thinking, I shouldn't be making any direct calls to the APIs from the browser, using some JS library, for it seems to me that it would be pretty insecure. Instead, I should keep it all traditional, by submitting requests to the web server and then letting it make the REST API call. This would be similar to the method of making REST calls from Android.
Am I correct in my thinking/approach?
Accessing your API should be the same no matter where the request is coming from. You just use an Authorization header with bearer scheme and stick the JWT token in there.
The way you get the JWT token is different though, as I explain in this answer. It all depends on how much you trust the client application.
If your client is a web application that queries your API from the server side, you can use the code authorization grant and get an access and refresh token for your API.
If you want to access your API from a JavaScript application, you have no way to hide app-keys or refresh tokens, so you should use the implicit grant.
If you know how to store secrets securely on your Android client, you could use the resource owner password grant.
The code authorization grant is definitively the most secure as it's much harder to compromise a server application than an application that runs on your machine.
Related
Well, in OAuth2 specification is foreseen cases where you are authenticating in an application that runs fully on the client side (browsers, mobiles, etc.) and so they are incapable of protecting their code/data.
In the memo regarding Security Considerations they say you should not store credentials in our code (for obvious reasons, I think):
https://www.rfc-editor.org/rfc/rfc6819#section-5.3.1
Also, in the memo about native clients, they highly recommend that an authorization server do not require an application secret:
https://www.rfc-editor.org/rfc/rfc8252#section-8.5
So, it should be possible to obtain an access token without using the client secret using a "client" grant type, like this:
https://www.oauth.com/oauth2-servers/mobile-and-native-apps/authorization/
Anyway, in the Github documentation, it's stated that the client_secret is mandatory to retrieve the access token:
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#2-users-are-redirected-back-to-your-site-by-github
By the official specification, you should be able to achieve this, but I couldn't find a way to achieve that using the Github OAuth, and here is my question:
Is there a way to use Github OAuth getting an access token without using the client_secret?
So, is there a way to use Github OAuth, get an access token without using the client_secret?
Not that I can see, when considering the authorization grant step
The application exchanges that code for the access token.
When the application makes the request for the access token, that request is authenticated with the client secret, which reduces the risk of an attacker intercepting the authorization code and using it themselves.
That means, if an application needs to automate that step on behalf of client, it needs to fetch that secret from a third-party referential, like a vault.
See for instance puppetlabs/vault-plugin-secrets-oauthapp, which is a plugin providing a secure wrapper around OAuth 2 authorization code grant flows, allowing a Vault client to request authorization on behalf of a user and perform actions using a negotiated OAuth 2 access token.
(here, Valut is hashicorp/vault)
I'm developing a REST API with a tightly coupled SPA as the only client of the mentioned REST API.
Let's say the SPA is available at myservice.com and api is under myservice.com/api. They're basically one service, just split at code level, and deployed at different root paths.
What I'm using for security right now is OAuth2 with ROPC (username/password) grant type.
Here comes the problem. I keep reading everywhere that ROPC is not secure and should not be used. What should I use then?
My REST API acts as an authorization server but it doesn't have any web interface itself. So any flow involving redirect doesn't really make sense. The SPA and API are so tightly coupled that for an end user they're basically one application. There's no 3rd party.
I could add simple login form to the API available at let's say myservice.com/login. But I'm struggling to see the difference that would make.
Security in this application is very important.
Here are my questions:
Is using ROPC really dangerous in this scenario?
What would be the perfect way for authentication and authorization?
Or maybe OAuth2 is completely redundant without a third party?
Technologies used:
Server: Spring Boot
Is using ROPC really dangerous in this scenario?
No, not really providing:
a) You don't store a user's password - maybe only use it to get the initial access and refresh token - although that could be tricky with an SPA.
b) Your SPA client and the resource API are owned by you, so you don't need the user to consent to specific scoped access for the SPA.
What would be the perfect way for authentication and authorization?
It depends on lots of things. Not enough info to try to answer that. OAuth2.0 (with a probably implemented Authorisation server) is a pretty good way for the example you have here.
Or maybe OAuth2 is completely redundant without a third party?
If other applications will use your API in time then OAuth2.0 is probably a good call. Otherwise you could probably use a more simple solution e.g. session cookies as all sits on same domain.
Answer to this can be taken out from OAuth 2.0 specification (RFC6749) itself. It define when ROPC grant is suitable for,
4.3. Resource Owner Password Credentials Grant
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viabl.
According to your explanation, you have tight coupling with SPA and backend. Also you have both authorization server and resource server built as one. This is completely acceptable implementation.
The authorization server
may be the same server as the resource server or a separate entity.
So what matter now is to clear out why you use OAuth 2.0 in your scenario.
If you are using OAuth 2.0 to obtain tokens, maintain them as defined through OAuth 2.0 specification, then this is completely oaky. But if you are doing this to follow a trend, think twice.
OAuth 2.0 implementation comes with it's own complexity. You have to maintain user identities, maintain tokens and renew them. You are building a complete authorization server by yourself. But this also have some advantages as well.
For example, same authorization server can be used to issue token for future integrations/secondary app. IMO, usage of OAuth 2.0 make integrations easy as it define a protocol for issuing tokens, renew and revoke them.! But in such integration scenario, may be you will require to use a different grant. Still, your API being authorized on token, you only need to worry about how new integration/application obtain tokens. This is better than using authenticated sessions
Going back to your questions,
Q : Is using ROPC really dangerous in this scenario?
As explained, if there is a correct trust relationship between client and authorization server, then it is fine. But be mindful about complexity comes with having a authorization server.
Q : What would be the perfect way for authentication and authorization?
OAuth 2.0 is for authorization. You obtain access token and use them to authorize against your protected APIs. From APIs you do a token validation to detect correct access levels/permissions.
If you want authenticaiton, then you must use OpenID Connect. It is a protocol extended from OAuth 2.0. And allows your application to authenticate the end user based on ID Token. You can use ROPC grant to obtain an ID token.!
Q : Or maybe OAuth2 is completely redundant without a third party?
Not necessarily. It allows you to design your APIs in a modern, standard way. Who know what future hold (again the integration scenario). Following a protocol allows that easy.
Only advice, follow specifications closely. Do not invent your own protocol/adaptation. It makes things harder to maintain.
I am trying to implement the Authorization Code flow described in RFC 6749 (OAuth 2.0) for a JavaScript-based application. I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end. Then all requests from the front-end to any protected resources go via the web server back-end, which attaches the access token to the request and proxies it on.
My question is how do I let the JavaScript front-end make use of these tokens in a secure way? I assume that I have to do something like set up a session on the web server and pass back a cookie that identifies the session. But this means that the JavaScript application then has a cookie that gives them the same privileges as if they just had direct access to the bearer tokens stored in the web server. How does having a web server to hold the tokens give extra security?
I understand that I should use a web server back-end as a confidential client so that it can protect the access token and refresh token returned by the authorization server and not pass them on to the JavaScript front-end.
No, it is a misunderstanding of the OAuth2 flows and goals.
Here is the OAuth2 main goal: your application (which can for instance be a JavaScript program running in the browser, a web server, both, etc.) MUST NOT need to know the user's credentials (most of the time a login/password pair) to access the service on behalf of the user.
Here is the way OAuth2 must be used to achieve this goal:
according to your needs, that is having a Javascript-based application running in the browser (i.e. not a node.js application), you need to use the OAuth2 implicit flow, not the authorization code flow. But of course, because your application is running in the browser, it will not be able to persist the credentials to access the resource offered by the service provider. The user will have to authenticate to the service provider for each new session on your application.
when your application needs to access the service provider when the user is not logged in, or when your application is able to persist credentials (because your application has its own credential system to identify its users), your application does not only rely on a JavaScript program running in the browser. It may rely only on a web server, or on both a web server and a JavaScript program that talks to this server. So, in those cases, you must use the authorization code flow.
So, as a conclusion, you have decided to add a web server to your application because you thought you had to use the authorization code flow. But in your case, you probably do not have to use this code flow, therefore you should select the appropriate code flow for your application: implicit code flow. And this way, you do not have to add a web server to run your application.
How does having a web server to hold the tokens give extra security?
This does not give extra security. Having a web server to hold the tokens is simply a way to let your application access the service on behalf of the user, in the background, when the user is not logged on your application.
While I agree with Alexandre Fenyo's comments, I just want to add the 2021 version. You should no longer be using the implicit flow as this is no longer considered secure.
For scenarios such as this where a JavaScript application has to handle tokens I would suggest using the Authorization Code flow with PKCE instead: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
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.
I am creating a solution that will contains a website and mobile apps. I will use Zend-Framework 2 for the website.
So, to make it good, I am wondering if it would be a good idea to build :
A REST web service (using zf2)
Another website that will call the REST ws (using zf2)
The mobile apps that will call the REST ws
I will use OAuth for the autentication and security.
My question is, if my website gets the data by calling the REST ws, it will have to make a database request at each call to check the token whereas if I do a "normal" website, my app will be able to use session to store the information of the connected user.
Because, for what I have read, there is no such thing as session with OAuth/REST so for each call, I have one more sql request to check the token validity.
Is it still a good idea to make a full REST service, even for the website or to have a "normal" website and also a REST service API just for the mobile apps ?
Thanks
Oauth is a server to server authentication framework. Like it is between mobile app and your API server , website vs your API server etc. You can adopt an approach where , you generate only one access token for your website client instead of multiple access token for each user from the website. This access token is stored in your webserver vs user cookie in website.Ultimately the aim is to identify all the clients of your REST WS and your website is one of its client and a very trusted one.
This way you can cache the access token to avoid db calls (typically cache time can be equal to or less than token expiry time). Do explore the multiple grant types specified in the oauth spec for this
Regarding maintaining session for user in your website, it is not dependent on whether the back end is a REST WS or not, it can be handled in your website