I'm currently having users login to my site using Auth0's redirect functionality. It's great, but my past experince with google's oAuth tells me there's a problem. With my other site, we do the same login, the user gets a JWT and posts that to my API server. My API server then takes that token and contacts google to ensure this is actually a token that they made. And THEN, I give them a Bearer code that they can use for when they want to access the database.
With Auth0, I can't seem to find any way to contact them from my API server and say, "Hey, someone sent me this token, it checks out that it isn't corrupted, is for a data that is in the future and it says you are the issuer and it has the proper Auth0 client id. So, did you issue this?"
I must be missing something.
Thanks everyone.
Related
I'm building an application where I want to be able to create and authenticate users using Discord and OAuth2. The reasons are:
The application can be considered a "companion" app to a Discord community I am running, and
I don't want the users or myself to have to deal with usernames and passwords
The application consists of a client desktop application and backend services. I have a fairly basic understanding on how I authorize the user with Discord:
Client application goes to backend endpoint /oauth/login and the user is redirected to the Discord app approval page
The user confirms and is redirected to the backend callback /oauth/callback with a code that can be used to fetch a pair of access and refresh tokens.
Frankly, from this point I am kind of stumped on how the rest of the authentication should work. I assume at least the following:
I need to create a user entry in my database with at least an UID (for simplicity the same as the one for the user in Discord), the access and refresh token pair. If user is already created, update the database with the new tokens.
Whenever the application needs user information from Discord it should use the access token. If it has expired, exchange the refresh token with Discord to get a new token pair.
But now what? This only authenticates the user against Discord. I want to leverage the fact that the user is authenticated with Discord to be authenticated to my application. Here are some general questions I have:
Do I make a new token for the user to use for subsequent requests to my backend endpoints? Or do I return the Discord access token to the desktop client?
What do I do when the token expires? Do I also need a "exchange" endpoint for the desktop client to refresh the token (possibly that just forwards to Discord to get a new token, depending on the answer to my previous question).
This all feels like it should be very basic, but I am out of my comfort zone here and need some help to be unblocked.
Thanks for reading!
Your own application should effectively have its own session system.
The easiest is likely to just use HttpOnly cookie-based sessions, which something like a Redis store (or Memory store if this is a toy project).
The session data on the server should contain information on which user is currently logged in. You should probably store the discord access and refresh token in a database.
The simplest way to deal with refreshing, is to simply call their refresh token endpoint as soon as you get a 401 response. If discord provides information on how long access tokens are valid, you could also preemptively refresh instead of only doing this when you get the 401. Your server does the refreshing, you don't need an endpoint for this.
Generally I can recommend that your server handles all interactions with the discord API, and never your client. (aside from the initial authorization step).
I am currently using a client-side React component to have a user login to Facebook via OAuth in my application. On the server-side, I use the npm package passport-facebook-token to validate the authenticity of the accessToken after a successful client-side login.
One practice I do not see often is in addition to asking Facebook if the accessToken is valid, shouldn't the server also check if the email provided by the client's payload matches the e-mail coming back from Facebook? Allow me to use defined client/server technologies to illustrate my question:
1) User uses React component on the client to authenticate with Facebook.
2) React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
3) The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token.
4) Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
My question is, should Node.js take the email that's also coming back from Facebook's access token verification payload, and verify that it is what came back from the React client? Would this not prevent someone from brute-forcing an accessToken and require them to not only have an accessToken but also know who the accessToken belongs to? This could prevent a user from submitting a bunch of HTTP POST requests to the Node.js server attempting different access tokens. They would not only have to guess an access token assigned to the application's clientID, but also know the e-mail it belongs to. Is this an over-engineered approach?
Really the best way I can think of to make your OAuth accessToken and 'code' value less prone to brute-forcing is using a Cryptographic Number Generator to create a 128-bit length string of random data and encoding it with base 64 to use as your code. It's extremely unlikely that it would be guessed by a computer or by someone redirecting to and from the authorization endpoint and the redirect-uri with query parameters.
Another method of fortification is limiting the rate of authorizations by IP address (which you can do instead of email through Node.js) but that is usually not a problem for most well-equipped hackers. I highly advise the first method for creating a more secure service.
Your approach to validate the email as well as the token is a bit superfluous because Facebook's opaque user access tokens are inherently tied to email.
From Facebook
An access token is an opaque string that identifies a user, app, or Page
"opaque" is defined by Auth0 here
Opaque Access Tokens are tokens in a proprietary format that typically contain some identifier to information in a server’s persistent storage
In your case, the identifier is the user's email, and the server belongs to Facebook.
I will elaborate further. Here is your step by step with some edits:
User uses React component on the client to authenticate with Facebook, inputting both their email and password directly to Facebook. React component gets the token from Facebook on login success.
React component successfully authenticates with Facebook and fires an HTTP request to the server with an access token and the user's email.
The server, running Node.JS and passport-facebook, now needs to verify the authenticity of the access token directly from Facebook. Facebook does not care for an e-mail. It will just verify the access token because the access token is already tied to the email.
Facebook returns a response to Node.js confirming the authenticity of the access token. The response also contains other metadata about the user, including their email and other profile data.
This is Facebook's bug bounty program. If their OAuth was really as cracked as to require a second email validation, it would have been patched almost immediately by this incentive.
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.
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
We would like to implement "Sign-in with LinkedIn" in our app. Since the app has JS fronted and RESt-based backend, we decided to exchange JSAPI tokens for REST API OAuth tokens as described here.
If a user successfully signs in, the frontend sends credentials cookie with client-side bearer token and member ID to the backend. On the backend we check if a user with such a member ID already exists and if not, we exchange JSAPI token for REST API OAuth token, retrieve user details from LinkedIn a store it in our database.
Now the question is if we can use that cookie to authenticate each user's request to our REST backend. After a user successfully signed in via JSAPI, the cookie should be automatically passed to our backend on all subsequent requests so we can check member ID. Are there any drawbacks that we missed? Or is this idea as a whole wrong?
Should we rather authenticate a user only once by means of the cookie and then issue our own authentication token and send it back to the client?
The way cookies work in general is they are passed on every request to the domain they belong to. LinkedIn is setting a credentials cookie to your domain.
As long as you are validating those credentials on every request it's perfectly acceptable to use their tokens as authentication.
Personally I don't find that to be a great idea and would prefer to validate their credentials once and create my own auth token to use from there on out. You can always set that token to expire at some-point and re-validate the LinkedIn credentials (which will still be getting sent on every request anyway). This limits the amount of times you're checking with LinkedIn and should increase the responsiveness of your app.
Either way could work.
If you are using the LinkedIn cookie to validate a user by member id, you should validate the cookie's signature on each request per section 2 of the doc you linked and question 2 of the FAQ.
Using your own token could make it easier to implement an account which belongs to your app and is not necessarily connected to LinkedIn, assuming there's the potential to either connect solely with some other service(s) or no 3rd part(y/ies). Still should validate any time you trust the member id in the cookie though.
The doc provides a validation example in PHP, and if you're interested in improving a ruby version, I have a shameless plug.
The flow that you've outlined in your latest comment of going straight for the OAuth tokens is the best way to go if you were only signing in to convert the JSAPI tokens to OAuth tokens and then not using the JSAPI further. If you were planning to actually use both the JSAPI tokens within your front-end app and the OAuth tokens on your back-end, then it's better to take the conversion route.