I am trying to create user roles like admin and users for my MERN project. But, I didn't get any good documentation or resources for it. So, please anyone who know good documentation or resources, suggest me or provide me a good sample of user authorization with MERN stack
You might find it helpful. It explains authentication and authorization in MERN stack on the basis or user roles.
https://abbasimusab2000.medium.com/authentication-with-react-and-node-de7384199a29
Although if you prefer to read official documentation here are few elements that will be useful for both authentication and authorization.
Backend
Let's consider you are creating/registering a user you can use bcryptjs for password hashing for security. Once the user is registered you can use bcryptjs function called comparesync to match hash and plain password, next you can create a token using jsonwebtoken and send it to frontend.
Frontend
Now on login if the user has entered correct credentials, then the backend will send a token, you can save it in local storage of cookie. For cookies you can use js-cookie.
Now if you need to add authorization you can send token with request on backend and then the backend will use a middleware for authentication by decoding the jwt and then will execute further logic.
Related
I am exploring possible solutions for creating something like "API Keys" to consume my API. The goal is to allow for users to generate one or many "API Keys" from the web app and use the static generated key from the CLI app.
The web app and the client app are already using standard OIDC with JWT tokens for authentication and authorization using RBAC (role-based access control). The CLI app can already authenticate the user through the standard browser flow (redirects the user to the browser to authenticate and exchange the token back to the client).
The "API Keys" solution I am trying to achieve should have some fine-grained options where it won't authenticate as the user, but will authorize the client on behalf of the user (something like the GitHub Personal Access Token).
To me it seems like a "solved problem" as multiple services provide this kind of feature and my goal is to do it the most standard way possible using the Oauth2/OIDC protocols but I can't find details on what parts of the protocols should be used.
Can anybody provide any guidance on how it is supposed to be done using the Oauth2/OIDC entities?
Can I achieve it by only using Role-based access control or do I need Resource-based access control?
It went through the path of creating a new client for each "API Key" created, but it didn't feel right to create so many clients in the realm.
Any guidance or links to any materials are appreciated.
Can anybody provide any guidance on how it is supposed to be done
using the Oauth2/OIDC entities?
OIDC is based on OAUth 2.0 so after user login you have id tokens, access token and refresh token on the backend side. To generate new access token without asking user for authentication data you should use refresh token: https://oauth.net/2/refresh-tokens/
Can I achieve it by only using Role-based access control or do I need
Resource-based access control?
resource-based access control is more flexible solution here, but if you business requirement is not complex, then role based might be enough.
It went through the path of creating a new client for each "API Key"
created, but it didn't feel right to create so many clients in the
realm.
It is one application so you should use one client with specific configuration for access token and roles/permissions for users.
Update:
We can use GitHub as an example:
User is authenticated during login
for OIDC code is exchanged for id token, access token and refresh token
session for user is set for web browser
User can request access token
in GitHub authenticated user can request github.com/settings/personal-access-tokens/new endpoint
request is accepted, because user is authenticated based on session
backend service responsible for returning access token can obtain new access token using refresh token from point 1.
access token is returned to GitHub user
To call your API in an OAuth way, CLI users must authenticate periodically. Resulting access tokens can be long lived, as for GitHub keys, if you judge that secure enough. The access token returned can be used exactly like an API key. There may be a little friction here between usability and security.
CONSOLE FLOW
The classic flow for a console app is to use the Native Apps Desktop Flow from RFC8252. This involves the user interactively signing in using the code flow, then receiving the response on a loopback URL. It is an interactive experience, but should only be required occasionally, as for GitHub tokens.
API KEYS
The access token returned is sent in the authorization header and you can use it as an API key. Access tokens can use a reference token format. to make them shorter and confidential, to prevent information disclosure. These will be more natural in a CLI.
API AUTHORIZATION
When your API is called, it must receive access tokens containing scopes and claims, to identify the user. This will enable you to authorize correctly and lock down permissions.
{
sub: 586368,
scope: repos_write,
topic: mobile,
subscription_level: silver
exp: ?
}
TOKEN REFRESH
Sometimes CLI access tokens are long lived, for convenience. A more secure option is for the CLI to use token refresh. It can then store a refresh token in OS secure storage, then renew access tokens seamlessly. My blog post has some screenshots on how this looks, and a desktop app that does not require login upon restart. The CLI needs to deal with expired access tokens and handle 401 responses.
DYNAMIC CLIENT REGISTRATION
Some developer portal scenarios use DCR. It is another option in your security toolbox. It could potentially enable a silent client per CLI user:
User runs a standard authentication flow with a DCR scope
This returns an access token that enables client registration
The resulting token is used to register a new client
This could potentially be a client ID and client secret used in a CLI
Afterwards, the user and client are bound together. Probably not immediately relevant, but worth knowing about.
We have Duende server for our UI and users provide their username and password and obtain an access token that is then used by our SPA app to call api's with the access token issued by our identity server.
I'm in a situation where I need to call the same API from a script and was wondering if RestSharp has some capability to obtain an access token if provided certain information (perhaps the users email/password etc that are typically entered into an interactive website) ?
I see that the RestSharp has some OAuth related "authenticators" but the documentation is unclear exactly what they achieve. I also dont see it mentioning anything about an email address and password.
I'm wondering if theres an option that is different than me generating a JWT elsewhere and supplying it directly to restsharp. I'd love if there was a programmatic way to generate the token directly from the IDP.
RestSharp documentation doesn't make it secret about how authenticators work. Both OAuth2 authenticators only add the necessary header or query string using the token you provide, but they don't request the token.
Duende server documentation explains in detail how to get a token based on the password grant (which is using the username and password).
Although the OAuth2 spec is stable, each API vendor has its own limitations. For example, Twitter API v2 only supports the client_credentials grant type. Therefore, it's not easy to create a generic OAuth2 client.
Still, it's quite easy to amend the Twitter authenticator sample from the docs and extend both request and response models to support the Duende server token request endpoint.
Yet another OAuth2 question that isn't quite covered elsewhere.
I'm using NestJS backend, React frontend, Passport and my own DB for authentication. Trying to add an
OAuth2 identity provider (Google).
I configured my NestJS app as an OAuth Client. After logging in I'm receiving the callback at which point I have an access_token and the requested user details extracted from the payload of the id_token. This is encapsulated in a class extending PassportStrategy(Strategy, 'google') and an AuthGuard('google') and much of it is handled automatically. Code here.
At this point however, I need to maintain an authenticated session between backend (NestJS) and frontend (React). I suppose I need a JWT, but I'm wondering about the best approach:
Can I use a token provided by the IdP (e.g. id_token or access_token)? So that I don't have to worry about issuing tokens myself. I.e. the frontend receives the token (either from backend, or the IdP directly), sends it on every request, backend verifies it with the IdP on every request (verifyIdToken or getTokenInfo of google-auth-library).
One drawback here is the extra network request every time. I'm not sure if there's a need for that because the IdP is only used to identify the user, not for access to other resources. Another drawback is that I need to store a refresh token and handle when the token expires (get new one, update it on the frontend).
So alternatively, could I just issue a JWT myself and not worry about checking in with the IdP? Once the JWT expires I'd need to prompt the user to log in again. In this case, I wouldn't need to store the IdP tokens. But is this good practice? One issue I can think of is that I won't detect if the user revokes access in the IdP (until the JWT expires).
I ended up issuing my own JWT tokens and managing User sessions in my app, as described in this article: OAuth2 in NestJS for Social Login (Google, Facebook, Twitter, etc)
probably my solution would be helpful.
you could access complete source code of my app that implemented with react typescript (redux toolkit rtk Query) and nestjs included of google oauth2 flow with passport.js. resource
I am looking for some advice on implementing authentication when the client and the server live in separate projects.
The Server
This API was built as an Express Server. It has routes for CRUD operations with a MySQL database. It also has a user model that utilize bcrypt to encrypt passwords. There is no Frontend, in this project.
The Client
This is a Vue project made with the vue-cli and hits the above API to get the data to display.
The Issue
I need to add authentication. I was thinking I would do this with express-session, but I am a little confused with how exactly it works. All of the tutorials I have seen use express-session in combination with passport. This seems fine, but in all the examples passport forwards to a login page that lives on the server. This is usually written in handlebars or some other templating framework. I am not sure the best way of implementing since the login page lives in the client project.
How I thought it worked (Am I missing something?)
I was originally of the impression that for a new user express-session would create a token that I would save in the users table (maybe generated at login and stored temporarily). Once the user logs in with the correct password this token is passed to the client to be stored as a cookie. When the client wants access to restricted data, it would pass the token as a Authentication header to the server to get permission.
The Questions
Since my projects are separated is passport still useful for my use case?
Is it secure to create the session cookie on the server and send the token to the client as a response to the client's login POST?
Do I need to store the session token in the database?
Is there a better option?
In my project I have almost the same setup, and I ended up with JWT to generate an access token.
The cycle begins with the user sending his/her email and password to my login endpoint.
In this stage I hash the password using some secret string, fetch the user from database and check if authentication succeed.
After that I generate an access token with an expiring time set, and I expected this access token in all protected routes.
With this approach you can easily implements refresh token to exchange at time to time, saving the refresh token in your database.
This is very simple and Is good to you understand how the process of authentication is done.
jsonwebtoken
I am playing with JWT and expressJS to learn something new, and come up with the idea to make my little JWT provider to use for all my future personal projects.
The idea is quite simple, my provider will register with facebook and twitter API, and will use passport to authenticate with them. I will also store users credentials so I don't need to worry about that in my other projects (these project will hold their info about users but various data from socials/passwords etc.. will be in the provider).
I coded this little workflow:
I register the app in my provider with a callback url
Put a button (e.g. 'Login with Twitter') on my project, that links directly to my provider
when I accept the Twitter conditions, twitter callback calls my provider that pick the right user and redirect to my project.
I am stuck on this last point, I would love to pass to my project the JWT token to use for its next requests, but how do I pass to it?
Cannot set cookie because domains are different obviously, I am missing something? Did I follow the wrong way?
The authentication flow you describe is similar to OAuth2. I suggest to read the RFC 6749. It explain the technical details to implement it. You can also refer to OpenID Connect. It is an extension of OAuth2 using JWT
Basically you need to create an access token after a successful login and return a redirection to the callback url. The adapted flow to your context could be the following
App redirects user to central login form
The server prompts user for the credentials :It returns an HTML form with the supported authentication methods, that can include a connection with a third party authentication provider
After a successful authentication, the server creates an access token. It can be a JWT
The server returns a redirection to the provided callback url. It includes an authentication code
The app request the authentication server using the previous code and get an access token
The token can be used by app to access to a protected resource
In Oauth2, the access token it is just a random string, but you can use JWT perfectly.