I've been recently learning to use JWT to secure user endpoints for an API I am creating for my mobile application.
I currently have a loginless system, where the app user gets automatically registered on the server, then gets automatically authorized and issued a JWT to use for all further requests. All the routes are protected except the following 2:
1) POST /register:
The most important one, that I could not figure out how to protect. Anyone with the URL can currently pass any login/password combo and consider himself registered, and subsequently obtain a JWT. I want to limit registrations to only my mobile application. How can I do that?
2) POST /auth: Used to validate login/password and issue JWT. I guess it's ok to remain unprotected if I manage to protect the registration. But I do actually want to restrict it to my mobile client as well.
Thank you.
To protect the registration, it is not enough to protect the end-point. Users always able to make requeststo your server.
You should do: Email validation, or Phone validations, or using Captcha. This will Prevents robots from registering.
Recommended Captcha Library by Google:
https://www.google.com/recaptcha/intro/index.html
Related
Please bear with me while I explain my problem and the solutions/guides I have found.
Description: In my company, we have one product that have multiple modules. Each module is its separate backend and frontend. We have JavaEE/JakartaEE with JAX-RS as our backend stack and React as for our frontend. Until now we are using Basic Authentication using the JavaEE Security via Sessions, but because the product is evolving and we need mobile clients and allow third parties to access the data, we have decided to integrate OAuth2/OpenID Connect into our application.
Since there are multiple implementations out there that provide OAuth2 functionality, we are currently looking into a few available options. (Keycloak and ORY Hydra for example). The decision which we will choose depends on how much work we want to do change the existing structure of the application how we handle the users in the database. But regardless of which implementation we opt for, we have similar questions going forward.
Questions
How do the react applications handle login process and token storage?
Every documentation says: If the user is not logged in s/he is redirected to the login page. Where after login and consent he is redirected back to the app (After completing the oauth2 workflow obviously) with the Access/ID Token for the resource server and/or Refresh Token for refreshing the Access/ID Token.
Now here is what is not clear to me:
Since this is our own React app, we do not want to show the consent screen, like in apps from Microsoft/Google etc you do not see any. I guess this is possible by setting a value in the request itself, or skipping the consent screen based on the client id but I just want to make sure.
Next is where do I store the Access and Refresh Token? Access Token should be sent as the Bearer token with each request. So it can be stored in local storage because they are short lived, but the refresh token should be stored securely. Like in a secure http cookie?. If that is the case, then the server has to set it. If this is correct is this how the flow will look like?
Our React App (Not logged In) --> Login Page (Another React Page) --> User Enters Credentials --> Java Backend --> Authenticates the user --> Initiate the OAuth2 process --> Get the Access and Refresh Tokens --> Set them as secure Cookies --> Return the authenticated response to frontend with the cookies --> Login Page redirects to the previous page --> User continues with the app
This does not feel correct. How would PKCE help in this case?
Assuming what I wrote above is correct, I would need different login flows when the users logs in from our own app or from a third party app. That can however be determined by checking client ids or disabling password flow for third party clients.
The same would be applicable then for the refresh token flow too. Because for my own app I have to set the cookies, for third parties this has to be directly from the OAuth Server
Resources I have read/researched:
https://gist.github.com/mziwisky/10079157
How does OAuth work?
Edit: Adding more links I have read
What is the purpose of implicit grant
Best practices for session management
RESTful Authentication
And of course various writings and examples from Keycloak and ORY Hydra also.
I am currently trying both Keycloak and ORY Hydra figuring out which fits our needs better.
Thank you all in advance!
You don't have to show the consent screen. Here's an example of a React app authenticating using the Authorization Code Grant: https://fusionauth.io/blog/2020/03/10/securely-implement-oauth-in-react (full disclosure, this is on my employer's site but will work with any OAuth2 compliant identity server).
The short answer is that it's best for you to avoid the implicit grant, and have the access and refresh tokens stored in some middleware, not the browser. The example in the link uses a 100 line express server and stores those tokens in the session.
I wrote a bit about PKCE. Excerpt:
The Proof Key for Code Exchange (PKCE) RFC was published in 2015 and extends the Authorization Code grant to protect from an attack if part of the authorization flow happens over a non TLS connection. For example, between components of a native application. This attack could also happen if TLS has a vulnerability or if router firmware has been compromised and is spoofing DNS or downgrading from TLS to HTTP. PKCE requires an additional one-time code to be sent to the OAuth server. This is used to validate the request has not been intercepted or modified.
Here's a breakdown of the various OAuth options you have (again, this is on my employer's site but will work with any OAuth2 compliant identity server): https://fusionauth.io/learn/expert-advice/authentication/login-authentication-workflows You can allow different flows for different clients. For example, you could use the Authorization Code Grant for third parties and the Resource Owner Password Credentials grant (which essentially is username and password) for your own applications.
I'm not sure I answered all of your questions, but I hope that some of this is helpful.
The OAuth 2.0 Security Best Current Practice should be consulted. Even though it is still a "Internet Draft" it is mature and has been implemented by several vender implementations.
In general the OAuth 2.0 Authorization Code with PKCE Flow is the recommendation regardless of the use of Bearer tokens or JWT.
You should also consider reading about WebAuthn (Where there is not password)
I have a database in firestore which is connected to a Android App, iOS App and a Website. Now for all these we need to sign in to access data.
My question is How can we specify a rule
for Android and iOS app, so that users should sign in to access data.
And another rule for Website, so that users who access website can decide whether to sign in or not but they can still access data.
Can anyone help me out?
There is nothing built in to Firebase Authentication or Cloud Firestore security rules to indicate what platform a request is coming from. To be honest, it sounds quite insecure: if a user doesn't have to sign in on your web app, what keeps all users from using that web app?
But if you really want to implement this functionality, the easiest way to do this, is to use anonymous authentication in the web app. With anonymous authentication, the user gets signed in without having to enter any credentials:
firebase.auth().signInAnonymously()
Now in your security rules, you can simply check for any authenticated user:
allow read, write: if request.auth.uid != null
This allows any authenticated user access to the data: from the web app this will be anonymous users, while from the native apps it'll be whatever sign in method you implemented there.
Once you add other sign-in methods to the web app, you can upgrade the user's anonymous account by linking the providers to a single user account.
Fair warning though that nothing stops users from creating their own app and running it against your project configuration. So they can create an Android/iOS app that also uses anonymous authentication. If you want to prevent that, things get quite a bit more complex...
Here's one way to do it:
In the web app, sign the user in with anonymous authentication. This means that the user doesn't need to enter credentials
In the web app, send a request to a Cloud Function you create.
In the Cloud Function, verify that the request is coming from your web app. I have no guidance here, since it's unrelated to Firebase.
If the request is coming from the web client, add a custom claim to the user account identifying the user as a web user.
admin.auth().setCustomUserClaims(uid, { isWebUser: true })
Once the client refreshes its token (this may take up to an hour, unless you force it to refresh), the custom claim will be present in all requests it makes. So you can from that moment on, check the claim in your Firestore security rules:
allow read, write: if request.auth.token.isWebUser == true;
I'm in the process of building a Google Chrome extension, and have some questions about how to implement security into the application.
I need to access a couple of Google API's so am going to be using OAuth 2.0 for that. So basically from the extension I know which user is logged into the browser.
My extension then needs to get and post data to my (nodejs) API service. I want to ensure that the user requesting data is the same user that is logged into the browser. Is there any way of using the previous Google authentication process to also authenticate communications between the extension and my API? I dont really want the user to have to log in again, to access my API.
I'm sure I'm missing something simple, and I've not been able to find anything that fits this scenario
Follow the OpenID Connect auth flow and you will get an access_token and an id_token. The acess_token you will use to use to make authenticated requests to Google APIs as usual. The id_token will be used as authentication with requests to your server.
When the requests hit your server you will need to validate the token and you can then use the contents of the id_token to identify the user.
User wouldn't have to login on auth process provided if user is already logged in and you are using a web application flow (not chrome.identity APIs) but user would see the consent screen atleast the first time. However you can skip the account selector screen if you already know the email address by providing &login_hint= parameter.
I'm building a mobile app and a ServiceStack web service back-end. The Authentication stuff in ServiceStack looks great but easy to get lost in its flexibility - guidance much appreciated. I'll be using my own db tables for storing users etc within the web service. I'd like to have a registration process and subsequent authentication something like this:
the user initially provides just an email address, my web service then emails a registration key to the user
the user enters the key. The app sends to the web service for registration: email, key & a unique device identifier.
the web service verifies the key and stores the email & device id. It responds back with an auth token that the app will use for later authentication.
Then subsequent web service requests would provide the device id and auth token (or a hash created with it). The app is not very chatty so I'm tempted to send the authentication details on each web request.
Question 1: Should I hook into ServiceStack's registration API or just add a couple of custom web service calls? e.g. without using ServiceStack's registration I would:
post to a registration web service with the email address and device id. My web service would send the registration email with a key and add a record to the user db table.
when the user enters the key it would again post to the registration web service, this time also with the key. My web service would validate the key and update the user table marking the user as registered, creating and recording the auth token & returning it to the caller
subsequent requests would be sent using http basic auth with the device id as username and the auth token as password. The service is not very chatty so creds will be sent with each request.
I'll implement a CredentialsAuthProvider that'll get the creds with httpRequest.GetBasicAuthUserAndPassword() and validate them against the db data.
But it feels like I should use registration built in to ServiceStack.
Question 2: What's wrong with passing the authentication details with each request? This would make it easier for composing my app requests but it doesn't seem 'done' based on the ServiceStack examples. Presumably that's because it's inefficient if you have lots of requests to need to re-authenticate every call - any other reasons? My app will only make a single web request at most every few minutes so it seems simpler to avoid having sessions and just re-auth each request.
Question 3: Am I on the right track subclassing CredentialsAuthProvider?
Question 4: Is there any point using the auth token to generate a hash instead of sending the auth token each time? All communication will be over https.
Answer1: It will be OK. if you give multiple call as per requirement. Normally authentication works based on cookie, now you can store it on client and/or on server and match the user with it. Again here if you are using device you, can always use device instead of user to map and authenticate user. Based on your requirement.
I will prefer to use provider as it hides many details which you need to do manually instead. You are on right track. There are many blogs specifically for authentication and how to create custom authentication with service stack. If you like let me know I have book marked some will give it you. Best way to search latest one is checkout twitter account of Servicestack.
Answer2: This is again, I say as per requirement. Now if your user will be in WIFI zone only. (Mostly true for business users), then there is not limit for calls. Just give a API call and do the authentication in background. Simple JSON token will not hurt, It is few bytes only. But again if you have big user base who is not using good internet connection then it will be better to store authentication detail on device and check against that. Just to save a network call. In any case network call is resource heavy.
Answer3: Yes you are on a right track. Still check out blog entries for more details. I don't remember the code snippet and how it works with last update so I am not putting up code here.
Answer4: This is answer is little complicated. Passing data over https and saving user from Identity fraud is little different thing. Now, if you are not generating auth token (hash based value) then you can pass user also over the http or https. Now, this can be used by another user to mock first user and send data. Even data is being passed through https but still data is getting mocked. Hashed based value is used to avoid this situation. And also there are couple of other business use cases can be covered using auth token.
Please let me know if I have understand you questions correctly and answered them?? or If any further details is required??
I have a webservice which acts as backend for smartphone apps.
I want to be able to authenticate users as painless as possible, but even though I thought I understood the OAuth I must admit there are some missing pieces here and there.
Authentication:
Let's say the user has an Android phone. He is probably already Authenticated to Google and it would be really nice if I could just extend this authentication to my webservice. Android has OAuth support so the users opens his app, grants permissions to use his google account and the app authenticates him to the web service.
Web service
Since the service should accept users from all kinds of devices it should not be Google specific. It should be possible to register an account and login from any device. I'm unsure if it is possible to register a new account with OAuth alone or if you need some other kind of authentication first - OpenID for instance.
How would the flow be for the generic webservice? A generic API for registering a user and granting him access to an API?
Furthermore - I do not want to control the devices connecting to this service. I can see OAuth requires a consumer_key and a consumer_secret. If I run everything through SSL - is the consumer secret still secret or can I just use some dummy values? Thus avoiding creating a device-registration system where people can acquire a consumer_secret?
For your case, if you want to use Google/Facebook etc as authentication providers, you will need to use the 'Authorization Code' flow of Oauth2. In this case, you register with Google/FB as a developer and get a client id and secret for using their API.
Then you obtain the Login with Google/Facebook button and code, which you will use to fire a "webview" or an embedded browser where the user will be taken to google/facebook and asked to provide his login credentials.
Upon success, an authorization code will be sent to a redirect url that you would have provided while registering as a developer at Google/Facebook. You will need to catch this authorization code and then again call the relevant API to obtain the access token, which you can then use to fetch the user's details to register him in case of first time or authenticate him if he's already registered through this method earlier.