React protect admin panel using JsonWebToken - reactjs

I got a single page app written with React and ReactRouter and the frontend seems to be easy going.
But I have no idea how to design a backend which is only accessable by admins. On the server-side I use a NodeJS / Express RESTful API which uses JWT (JsonWebToken) for authentication.
Do you have any ideas?

You can use Express Middleware to check and validate JWT. If the JWT is valid then proceed with the API otherwise redirect to login. There are lots of articles available on ExpressJs site about middleware.

One great option is express-jwt
You import it, make a middleware, and place it before any protected route. If the token is valid, req.user will be set with the JSON object decoded to be used by later middleware for authorization and access control.
const jwt = require("express-jwt");
const auth = jwt({
secret: jwt_secret
});
router.get("/secret/:uid", auth, profileCtrl.secret);

Related

How Laravel Auth works with Token JWT?

The user login in with Auth::atempt(), and this generates an authentication "state" in Laravel - the auth::user().
At the same time, I can generate a JWT token with, for example, the same data as auth::user() and send it to the frontend, storing it in local storage.
OK. Only with auth::user() I could already check the user's authorization to perform actions, right? For example:
if(auth::user()->role === "admin") { //... }
So, what is the purpose of JWT values if they are the same of the auth facade? Because Laravel would already authenticate with auth, and it store all user values that can be used for authorization, so I don't understand the purpose of using it with Laravel.
My application uses the react scaffolding, and is a frontend SPA.

Azure ad authentication SPA token not able to authenticate by my API

I have API and SPA at same azure. I already set the Expose an API and gave permission on my SPA.
but when I login on my SPA the return token that I pass to my API is not authorized.
any thing else I need to do into my SPA?
I use React js and MSAL to login.
You may miss the scope. The scope is format as api://{client_id}/.default.
There is a sample using the on-behalf-of flow: https://github.com/Azure-Samples/ms-identity-javascript-react-spa-dotnetcore-webapi-obo
In ProfileSPA/src/utils/authConfig.js:
export const apiConfig = {
resourceUri: "https://localhost:44351/api/profile",
resourceScopes: ["Enter the API scopes as declared in the app registration 'Expose an Api' blade in the form of 'api://{client_id}/.default'"]
}
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#use-the-access-token-to-access-the-secured-resource

How to authenticate in asp.net core rest api from react app

I have 2 asp.net core web applications: REST API and React UI. React UI uses default Individual User Accounts option for authenticating. They are separate solutions.
What I want is to authenticate in API using this default authentication. But I'm don't know how can I do this. So what I want is
Make a call from UI -> Grab user credentials -> Go to API method -> Validate user (e.g. role) -> Return response
As far as I know, default authentication sets AspNetCore.Identity.Application cookie that used for auth in react. Probably, I can somehow parse it or just use it to authenticate on API side. I thought it's JWT token, but seems like it's not
React application sends request:
Url: /auth
Body: JSON.stringify({username: "john", password: "password123" })
REST API handles /auth request
Validate that username exists
Checks that password is correct
Either sets a cookie that the user is signed in or returns a token that the React app can save for future requests
React app sends request to get items
Url: /items
Headers, include token or set withCredentials to pass cookie
REST API handles /items request
Makes sure cookie/token is set
Validate token/cookie
Return items if everything is ok.

Next.js Authentication Strategies

I've been trying to implement a reliable authentication flow for a Next.js project but I'm completely lost now. I've already seen the examples repo of Next.js. But I have a lot of questions for a complete solution.
I have a express.js API and a separate Next.js frontend project. All the data and the authentication is handled by the API. Frontend just renders the pages with SSR. If I would just create a monolith project, where rendering the pages and all the data is handled by a single server (with a custom server option for Next.js I mean), I would just use express-session and csurf. It would be a traditional way to manage sessions and create security against CSRF.
Express.js API is not a requirement. It is just an example. It could be a Django API, or a .Net Core API. The main point is, it is a separate server and a separate project.
How can I have a simple, yet reliable structure? I've examined some of my favorite websites (netlify, zeit.co, heroku, spectrum.chat etc). Some of them use localstorage to store access and refresh tokens (XSS vulnerable). Some of them use cookies and they are not even HTTPOnly (both XSS and CSRF vulnerable). And examples like spectrum.chat use the way I mentioned above (cookie-session + preventing csrf).
I know there is the giant hype around the JWT tokens. But I find them too complex. Most of the tutorials just skips all the expiration, token refreshing, token revocation, blacklisting, whitelisting etc.
And many of the session cookie examples for Next.js almost never mention CSRF. Honestly, authentication is always a big problem for me. One day I read that HTTPOnly cookies should be used, next day I see a giant popular site not even using them. Or they say "never store your tokens to localStorage", and boom some giant project just uses this method.
Can anyone show me some direction for this situation?
Disclaimer: I am a maintainer of the free open source package below, but I think it's appropriate here as it's a common question there isn't a great answer for, as many of the popular solutions have the specific security flaws raised in the question (such as not using CSRF where appropriate and exposing Session Tokens or web tokens to client side JavaScript).
The package NextAuth.js attempts to address the issues raised above, with free open source software.
It uses httpOnly cookies with secure.
It has CSRF protection (double submit cookie method, with signed cookies).
Cookies are prefixed as appropriate (e.g. __HOST- or __Secure).
It supports email/passwordless signin and OAuth providers (with many included).
It supports both JSON Web Tokens (signed + encrypted) and Session Databases.
You can use it without a database (e.g. any ANSI SQL, MongoDB).
Has a live demo (view source).
It is 100% FOSS, it is not commercial software or a SaaS solution (is not selling anything).
Example API Route
e.g. page/api/auth/[...nextauth.js]
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
const options = {
providers: [
// OAuth authentication providers
Providers.Apple({
clientId: process.env.APPLE_ID,
clientSecret: process.env.APPLE_SECRET
}),
Providers.Google({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET
}),
// Sign in with email (passwordless)
Providers.Email({
server: process.env.MAIL_SERVER,
from: '<no-reply#example.com>'
}),
],
// MySQL, Postgres or MongoDB database (or leave empty)
database: process.env.DATABASE_URL
}
export default (req, res) => NextAuth(req, res, options)
Example React Component
e.g. pages/index.js
import React from 'react'
import {
useSession,
signin,
signout
} from 'next-auth/client'
export default () => {
const [ session, loading ] = useSession()
return <p>
{!session && <>
Not signed in <br/>
<button onClick={signin}>Sign in</button>
</>}
{session && <>
Signed in as {session.user.email} <br/>
<button onClick={signout}>Sign out</button>
</>}
</p>
}
Even if you don't choose to use it, you may find the code useful as a reference (e.g. how JSON Web Tokens are handled and how they are rotated in sessions.
I've had to think about this as well for my current project. I use the same technologies: an ExpressJS API and a NextJS server-side-rendered front-end.
What I chose to do is use passport.js in the ExpressJS API. TheNetNinja on YouTube has a really good playlist of this with 21 episodes. He shows you how to implement Google OAuth 2.0 in your API, but this logic transfers to any other strategy (JWT, Email + Password, Facebook authentication etc.).
In the front-end, I would literally redirect the user to a url in the Express API. This url would show the user the Google OAuth screen, the user clicks on "Allow", the API does some more stuff, makes a cookie for the specific user and then redirects back to a url in the front end. Now, the user is authenticated.
About HTTPOnly cookies: I chose to turn off this feature, because I was storing information in the cookie that I needed in the front-end. If you have this feature enabled, then the front-end (javascript) doesn't have access to those cookies, because they are HTTPOnly.
Here's the link to the playlist I was talking about:
https://www.youtube.com/watch?v=sakQbeRjgwg&list=PL4cUxeGkcC9jdm7QX143aMLAqyM-jTZ2x
Hope I've given you a direction you can take.
EDIT:
I haven't answered your question about CSURF, but that's because I'm not familiar with it.
I've finally found a solution!
Now I'm using csrf npm package, not csurf. csurf is just turns csrf into an express middleware.
So, I create a csrfSecret in the getInitialProps of _app. It creates the secret, sets it as a httpOnly cookie. Later, it creates a csrfToken and returns it with pageProps. So, I can access it with window.NEXT_DATA.props.csrfToken. If user refreshes the page, csrfSecret remains the same, but csrfToken gets renewed.
When I make a request to the proxied "/api/graphql API route, it first gets the csrf token from x-xsrf-token header and verifies it with the csrfSecret cookie value.
After that, it extracts the value of authToken cookie and passes it to the actual GraphQL API.
API is all token based. It only needs a non-expiring access token. (BTW, It doesn't need to be JWT. Any cryptographically strong, random token can be used. Which means a reference/opaque token.)
CSRF check is not needed for the actual API, because it doesn't rely on cookies for authentication. It only checks authorization header.
Both authToken and csrfSecret is httpOnly cookies. And I never even store them in client-side memory.
I think this is as secure as I could get. Now I'm happy with this solution.

How to pass basic auth header to REST endpoint after Forms Authentication sign in?

I have a Backbone/RequireJS application built on top of .NET MVC4. I am using Forms Authentication to authenticate the user against our back end data store, and this is working great.
Our services layer is a .NET Web Api Project (RESTful API), and is using a tokenized approach to auth (initial request includes basic auth header. If auth is successful, response payload includes authentication token. Subsequent requests pass the token).
What I'm not sure about is how to now authenticate against our services layer. I'm sure I'll have to pass the auth header, but not sure how to generate the token, as I won't have username/password in my JS.
Should I bypass Forms auth altogether here, and simply make an ajax request over SSL? I can POST to the /Account/Login action just as well, and use the Membership Provider to validate credentials. If successful, I can add the Auth header for initial request & use auth token for subsequent requests.
Example of adding auth header / custom token here:
$.ajaxSetup({
'beforeSend': function (xhr) {
if($.cookie("AuthToken")) {
xhr.setRequestHeader("CustomTokenHeader", $.cookie("AuthToken"));
} else {
var token = methodToBase64EncodeUsernamePassword(username, password);
xhr.setRequestHeader("Authentication", "Basic " + token);
}
}
});
Take a look at this solution, which is based off a screencast I cannot seem to find again. If I can find it, I will update the answer. You should be able to follow the solutions easily though. The one you are looking for is PerRouteMHOwnershipSample. I believe the best practice is to 'bypass Forms auth altogether here, and simply make an ajax request over SSL'. Any api route you want to secure, will be filtered and a token will then need to be passed from your app and decoded on the server. I would personally not look at using Forms Authentication to secure your api.

Resources