How to authenticate requests using ServiceStack, own user repository, and device ids? - servicestack

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??

Related

Azure Active Directory add custom data to Oauth2 token

I'm using the auth endpoint https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token programmatically (Nodejs) for getting back a token that will be used against my API. I have everything properly configured to send the request using a "Client secret" I setup on the Azure Portal - App registration service.
This issues a valid token that I can later check with the help of the Passport azure AD npm library. However I've been looking for a way of somehow adding more metadata to that token (i.e. a custom user name) so that when it gets validated and parsed by my server upon future requests I can extract this information.
When issuing tokens using a frontend application library (like msal) I have access to some of the user's information on the token (like its oid and email address). I'd like to be able to "extend" the token generated by the client secret to also contain a couple custom fields, which I can use after validating and parsing it.
Hopefully that's clear enough. I'm lost on how to achieve this. Thanks
It is a common requirement for APIs to authorize based on claims stored in the business data, eg roles or other custom data.
OPTION 1
Ideally the authorization server can reach out at the time of token issuance to an API or database to include the custom claims. This is not always supported though.
OPTION 2
Another option is for the API to process the incoming access token into a ClaimsPrincipal and to include custom values at that point. For an example see this code of mine.
PRIVACY
When adding more claims, you should also be careful about revealing sensitive data in JWTs returned to internet clients. Eg if you include names and emails, they are easily readable, and this can sometimes be a security concern.

Api design with authorization from one service to another

I am creating a Shopify app which has its own Shopify oAuth. I have built an external NodeJS application to handle all the settings, handling all the dashboard analytics, etc via api's.
I need to connect these two services together. Upon installing the application on Shopify I have an endpoint on my external service to create the shop in my table. Although now on I need to allow ONLY that store to be able to view their data / update it and not modify the request to get other stores information. Also not allow the public to view these endpoints.
I was thinking of generating an Api token on the NodeJS (external) application and saving it in the Shopify Database (Another database of stores), then passing it on every request and verifying it on the external application side. I like this approach but I also feel its not as secure since someone can steal a token.
[You also don't actually "create" an account, you just Install the app, and the app makes an Api request for a new "store" entry]
I was thinking of using JWT for that but possibly can't.
Another option was combining the Api token and creating 1 admin user on the external NodeJS so that a Bearer token w/ the Api token need to be passed. This gives 1 extra layer of security since they would "need" to have this app install at least in Shopify.
What are some suggestions that I can look into?
Shopify's docs recommend a number of libraries for using their OAuth, and I would recommend using one of those until you're more familiar with the OAuth workflow. They also supply a template project that already has this wired up in an express server. Depending on where you are with your external project, you might consider starting with that and moving your existing code into it, but if not, the web/middleware section will give you an example of what to do.
To answer your specific question, I think you might be misunderstanding how OAuth works, as you would likely not generate any tokens yourself. There are a lot of lengthy explanations out there (a few here: What exactly is OAuth (Open Authorization)?), but for a really basic rundown, let's first consider a really simple traditional authentication workflow:
user registers on your site, and you store their username and a hash of the password in a table such as users
when the user tries to log in, they send a username and password. You check this against your users table, and if it matches, you generate an auth token. You then store this token along with the username in a table such as auth_tokens
for subsequent requests, they include this auth token as a header. For every single request, you look up the token in the auth_tokens table, and if it's there (and hasn't expired), you assume the request comes from the username you stored with the token and restrict access accordingly
With OAuth, you're offloading all of that to a third party. This is oversimplified a bit, but effectively works like:
user registery with third-party
when the user tries to log in to your site, you redirect them to third-party, and they log in there
third-party gives them a token and redirects them back to your site
your app calls third-party with the token, and if it's valid, third-party gives you their username (and some other info). You trust third-party, so you take their word for it that the request comes from that user and restrict access accordingly
In the case of shopify, the "other info" will include the shop, and your app can then choose to only show them info for that shop.
https://github.com/Shopify/shopify-api-node/blob/main/src/auth/session/types.ts
EDIT based on comments:
If I understand correctly, you mean that, after doing something in Shopify, you also want the same person to use your core application to update things in this external service WITHOUT Shopify in the middle, and you want to verify that it's the same person.
If so, your hesitation about the token is correct. You would essentially be handing out a password that works forever and storing it in an insecure place. There are 2 better options.
I know NOTHING about this, but it does look like Shopify has an option to be an OAuth provider for your core application as well. https://shopify.dev/api/multipass. This is essentially the same as a "Log in with Google" option. This way, you're using Shopify's tokens for everything.
Your application could have its own login, and you would need to associate your user with theirs. One easy way to do that would be using the email address. Nested in that session token you get from Shopify, you have the onlineAccessInfo:
export interface OnlineAccessInfo {
expires_in: number;
associated_user_scope: string;
associated_user: {
...
id: number;
email: string;
email_verified: boolean;
...
};
}
You would need to keep a record of this info when requests come from Shopify. If they have verified the address (the email_verified field is true), and you have verified the address, then you can assume they're the same person. You could either require that they register on your site with the same email, or you could verify it separately if they did not.

PHP REST API Key and User Token Authentication

I wanted to check with you guys if my API Key and user Authentication scheme makes sense or not. My server side code is in PHP and the Database is MySQL. This is the scheme I have in mind:
I am implementing a REST API in a backend server that will be called by a Mobile App (for now). At this point, I only want known Mobile Apps to connect to this API. So I am using a one-time API Key that has been given to the Mobile App during installation. Every request from the App passes the API Key that my API checks before going further. This Key is stored in a Database table. This completes my API Key checking and seems to allow only known Apps from calling my APIs.
Next, I also have certain services after calling the API which only authenticated users are supposed to get access to. For this, the Mobile App logs in with a Username and password which is authenticated in the User table of my Database. If it passes, the server generates a User Token and passes it to the Mobile App. The User Token is also saved in the User table against that User. All subsequent requests from the App (which requires user authentication) passes this User Token which is checked in the User table in the Database for User Authentication. If the Mobile App logs out, this User Token is deleted from the User table. I also have provision to add "TimeToExpire" for this User Token which I will implement later.
I would be really grateful if you guys could tell me the following:
Does the above structure makes sense for App Authentication and User Authentication?
I am a little lost as to what will happen if I ever need to change the API Key (for whatever reason). Not sure how that will be sent to all the Apps. Google Messaging seems like one possible way to handle that.
For the App Authentication, does it make sense to keep the API Key in a Memcached object? Since all requests from the Apps are authenticated, I don't want to go to the DB everytime. And pros/cons?
Along the same lines, does it also make sense to have the User Token in a Memcached object as well? Pros/cons?

how to secure azure mobile service / html - javascript

When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.

using facebook client flow to authnticate and login on app/site

Other then the fact that when using facebook's client-flow you get an access token right away, and when using the server-flow you first get an authorization code that you have to exchange for an access token, What is the difference between the two flows and when should I use each of them ?
more specifically can I use client-flow and still be able to securely log a user into my application/site?
At first glance I though that I could take the access_token and id I got on the client (via client-flow), send them to my server and then if a graph api call for that ID and token does not break I can assume I am dealing with this user and log him into my site based on his FB ID.
On second thought it looks to me that If I don't follow the server-flow there is no way to securely use the client id & access_token to log the user into my application/site.
The reason I say this is that another (hacker) app owner that "shares" a user with my app. might take the access_token and and ID he (illegitimately) got for user on his authorization flow, and fake a call to my site with this data causing me to log him in as if he was this user.
Am I missing something here?
Should this not be written in big red letters on the first paragraph of https://developers.facebook.com/docs/authentication/ ?
Oauth 2 (http://oauth.net/2/) is what Facebook uses. For the most part it is the most secure interface available. If there was a way for a user to take an access token for one app and then use it in another app, then oauth2 will need to be patched (or Facebook oauth2 will need to be patched).
If you think you found a way to hack it, then you should get your $500.00 prize from http://www.facebook.com/whitehat/bounty

Resources