Displaying token to user - swift

I have an auth system using JWT in my iOS app. I receive an access token from the server and use it for each request. Can I show that token to the user? Why it might be unsafe?

Whether it is safe to show the JWT to the user depends on the information in it and your organization's policy wrt. that information. If there's only information about the user in the token, it is OK in most cases. But if there's information that you want to hide from the user - which may also include information about that user that is intended for other recipients only - then no.
Basically the token is available to the user anyhow, since it is in an app on his device. He could get to it by intercepting the communication (endpoint) or inspecting the memory contents.
So if there is information you really need to hide from the user, the token issuer should encrypt the JWT.

Related

Is it right to put the user's identifier in the payload of the access token(JWT)?

I am currently developing financial services as a personal project.
In order to strengthen security in the project, it is designed and implemented to process authentication at the gateway stage using AWS API Gateway.
I tried to log in using a mobile phone number and the received authentication number, and I don't think this is appropriate for Cognito and IAM identifiers, so I'm going to run the Node Auth Server that issues and verifies JWT tokens in AWS Lambda.
In the process, I tried to include an identifier such as user_id or uuid in the payload of the JWT token, but my colleague opposed it.
His opinion was that access token should only engage in authentication and that the token should not contain a user identifier.
I agreed with him to some extent, but if so, I wondered how to deliver the user identifier in an API such as "Comment Registration API".
Should we hand over the user identifier along with the access token to the client when login is successful?
in conclusion
Is it logically incorrect to include the user identifier in Access Token's Payload?
If the answer to the above question is yes, how should I deliver the user identifier when login is successful?
I wanted to hear the majority's opinion, so I posted it.
Thank you.
Typically you want enough information in the access token so that you can also do proper authorization about what the user/caller is allowed to do.
Typically, you separate authentication and authorization like the picture below shows:
So, to make an effective API, you do want to avoid having to lookup additional information to be able to determine if you are allowed to access some piece of data or not. So, I typically include the UserID and some other claims/roles in the token, so that I can smoothly let the user in inside the API.
However, adding personal information in the access token might have some GDPR issues, but sometimes it might be necessary to also add. But I don't see any issues adding information like UserId and roles in the token.
Yes it is logically correct and a normal thing to do. To see how to do it in a Node Auth Server, you can look at this: https://auth0.com/blog/complete-guide-to-nodejs-express-user-authentication/

Facebook oauth2 - secure after-login use

I would like to ask little theoretically.
I have an angular6 + spring app that has its own client, app-specific client data.
These data can be divided into two groups
managment-data: Like client roles that allow client to visit different parts of app
client-data: personal settings, history of activities etc.
Because I would like to make login as user-friendly as possible, I would like to implement facebook login.
After user click "FB login button", facebook returns me some-user info and mainly a security token. How could I use this to securely communicate with my BE.
When someone sends request to BE, I need to be sure, that its the same person that logged in to facebook.
If I send this token as part of request, what stops possible attacker to somehow obtain token and then impersonate original user?
In what form I should send data I got from Facebook to my own server?
How should I work with token on server?
How can I validate its authenticity?
Thank you for answers
Filip Širc
You should look into the usage of OpenID Connect along with OAuth protocol. It allows you to authenticate the user to your client application (Angular6 + Spring app) to verify the user details.
When you are sending an access token to access a certain resource, you should avoid sending it as a request parameter. Usually it is encouraged to send it under the Authorization header of the request as a bearer token. However, if you want it to be extra secure, you could encode the token before sending so that it would be difficult to decode it and steal any valuable information.
Also, when you are sending sensitive information, it ise better to send them in the form of a JSON Web Token (JWT). You can use a third party library to create a jwt to include the information that need to be sent to the server. You can sign the jwt with your own signature which can be validated later. Refer https://www.rfc-editor.org/rfc/rfc7519 for detailed information about jwts.
You should use the claims in your access token to grant a user access to the resource you are protecting. Since most of the tokens are sent in the form of jwts, you can decode them and get check the necessary claims such as scopes, audience (client app), subject (user), etc.
Most importantly, you should validate the signature of the token sent from Facebook to make sure its an authentic one. For this, you have to get the public key details from Facebook's jwks endpoint and validate the signature using a third party library (auth0, nimbusds, etc.). Facebook's digital signature will be unique and this verification process is the best way to ensure the security. Also, you can check whether certain claims in the token match your expected values to validate the token. This can also be done through libraries such as ones mentioned above. Here's auth0 repo for you to get a general idea.

REST API user and client authentication

I am building a REST API as the backend for a mobile app. I would like to check if the requests made to the API are coming from our mobile app. However, the API will require end users to login in order to access certain endpoints.
My questions is, how could I authenticate all incoming requests to make sure they are coming from our own app, while also authenticating the end users for some requests?
I was thinking of sending an API key with all requests in the Authentication HTTP Header to authenticate the mobile app, and (separated by a comma) also send along a JWT for authenticating the end-user. While this could work, it seems a bit "hacky".
What is the standard way of authenticating both the mobile app and the
end-user of the mobile app at the same time?
Using an application token and a user-specific session token is one method of separating authentication of the two. The application token would be unique for your application, and should be obfuscated so that inspection of the client's binary would not lead to easy detection of the token. The user-specific session token should be generated when the user is logged in. The client adds this user session key to future API calls, the server will check if the session key is valid, and can use it to look up any session state stored for the client.
However, optimally, you would implement the full oauth2 spec. as outlined in this ultimate guide to mobile API security:
Here’s how OAuth2 token authentication works from a user perspective
(OAuth2 calls this the password grant flow):
A user opens up your mobile app and is prompted for their username or email and password.
You send a POST request from your mobile app to your API service with the user’s username or email and password data included (OVER SSL!).
You validate the user credentials, and create an access token for the user that expires after a certain amount of time.
You store this access token on the mobile device, treating it like an API key which lets you access your API service.
Once the access token expires and no longer works, you re-prompt the user for their username or email and password.
What makes OAuth2 great for securing APIs is that it doesn’t require you to store API keys in an unsafe environment. Instead, it will generate access tokens that can be stored in an untrusted environment temporarily.
This is great because even if an attacker somehow manages to get a hold of your temporary access token, it will expire! This reduces damage potential (we’ll cover this in more depth in our next article).

OAuth - what to store on disk

TL;DR When using google oauth on desktop app, what to save on disk to avoid repeated sign in? Save the google user id? or the token? or an session id?
I'm creating an little desktop app, whitch must authenticate to my REST API server. I'm using google oauth2 for that.
The idea is, that when the desktop app will be authentivated, it generates some data that will be send to my server. The server will store the data with the google user id received from https://www.googleapis.com/userinfo/v2/me.
On the first run of the desktop app, it will open the default browser, with and url for my server and start an local http server. then:
my server will redirect the browser to google (with the clientid, secret, etc.)
user logs in and it will be redirected back to the server with the oauth code
server uses the code to get the token, and then the user profile and stores the token and the profile in db, then redirects the browser to localhost with an paramerer
the desktop app catches the parameter and stores it in an file on the disk
next time the desktop app will start it only reads the file for the parameter to send the generated data with it to my server
my question is: what the parameter should be? the google user id? the oauth token? an generated session id for this desktop app? or something else?
when it will be the google user id, it can conveniently sent the data with the user id and the rest server will just store it in db as is. but I don't think it's safe
when it will be the token, the rest server has to with every request also get the user profile from google with the token. and imho sending the token with every request isn't safe either
generating an session id means to store it with the user and the token on the server and the desktop app will just store it and send it with every request. but I don't know if it's safe to do that
As it's normally the case in software development you have a couple of options depending on requirements.
The mandatory requirement is that your client (desktop) application needs to send something to your REST API so that the API can perform up to two decisions:
Decide who the user is.
Decide if the user is authorized to perform the currently requested action.
The second step may not be applicable if all authenticated users have access to exactly the same set of actions so I'll cover both scenarios.
Also note that, for the first step, sending the Google user ID is not a valid option as that information can be obtained by other parties and does not ensure that the user did authenticate to use your application.
Option 1 - Authentication without fine-grained authorization
Either always sending the id_token or exchanging that token with your custom session identifier both meet the previous requirement, because the id_token contains an audience that clearly indicates the user authenticated to use your application and the session identifier is generated by your application so it can also ensure that. The requests to your API need to use HTTPS, otherwise it will be too easy for the token or session ID to be captured by an attacker.
If you go with the id_token alternative you need to take in consideration that the token will expire; for this, a few options again:
repeat the authentication process another time; if the user still has a session it will indeed be quicker, but you still have to open a browser, local server and repeat the whole steps.
request offline_access when doing the first authentication.
With the last option you should get a refresh token that would allow for your application to have a way to identify the user even after the first id_token expires. I say should, because Google seems to do things a bit different than the specification, for example, the way to obtain the refresh token is by providing access_type=offline instead of the offline_access from OpenID Connect.
Personally, I would go with the session identifier as you'll have more control over lifetime and it may also be simpler.
Option 2 - Authentication + fine-grained authorization
If you need a fine-grained authorization system for your REST API then the best approach would be to authenticate your users with Google, but then have an OAuth 2.0 compliant authorization server that would issue access tokens specific for your API.
For the authorization server implementation, you could either:
Implement it yourself or leverage open source components
⤷ may be time consuming, complex and mitigation of security risks would all fall on you
Use a third-party OAuth 2.0 as a servive authorization provider like Auth0
⤷ easy to get started, depending on amount of usage (the free plan on Auth0 goes up to 7000 users) it will cost you money instead of time
Disclosure: I work at Auth0.
There should be no problem sending the access_token with every request since they are created for that purpose and are thus short lived. You can use the Google Authorization Server endpoint to verify a token instead of using it to do a request for a users profile.
If you're only relying on Google for authentication, here's how your workflow can look:
the client (desktop application, in your case) retrieves the
Google id_token following the user's log in, and then sends it to
the server
the server validates the integrity of said token and extracts the user's profile data; this could mean a simple GET on Google's endpoint to verify this token: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
On subsequent requests, nothing should change really, except that the user's login process will be automated (since he's given permissions & all), and thus much faster. #danielx is right, there's no problem with sending the token each and every time.

Token Authentication and logout functionality

In a very basic Token authentication the login process in nothing but providing the credentials and obtain the token. With RESTful API, the token is included in the header for any API calls to imply that the user is logged in.
My question is, what would the logout procedure look like?
Deleting the token at server-side? What if the user is going to logout from web but wanna stay logged-in in mobile app?
Deleting the token from client side? Should the server not enforcing that?
How should the server go about invalidating a token?
How are logout mechanism implemented?
I think that the logout action simply invalidate the token on the server side (delete it in your database, set a flag expired to false, ...). If you want to support several kinds of REST clients, you should be able to specify for which device you want to obtain a security token. In this case, you will be able to invalidate them separately.
To provide the device kind, you can levevage the header user-agent or provide your own header.
Perhaps this link could help you in the design of your token management: http://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/.
You talked about a Web mode. For this use case (which is a bit particular since the browser holds the token for you implicitely), I suppose that you leverage cookies. So yes, for such particular use case, the corresponding cookie must also be invalidated.
Hope it helps.
Thierry