Reputation: 3833
In my node project I have the following basic code to connect to Azure via a token. The login/logout works great together with our Azure:
const express = require("express");
const msal = require('@azure/msal-node');
const SERVER_PORT = process.env.PORT || 3000;
const config = {
auth: {
clientId: "XXX",
authority: "https://login.microsoftonline.com/common",
clientSecret: "XXX"
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
const pca = new msal.ConfidentialClientApplication(config);
const app = express();
app.get('/', (req, res) => {
res.send("<a href=\"login\">Login</a> <a href=\"logout\">Logout</a>");
});
app.get('/dashboard', (req, res) => {
// check here for valid token...
});
app.get('/login', (req, res) => {
const authCodeUrlParameters = {
scopes: ["user.read"],
redirectUri: "http://localhost:3000/redirect",
};
pca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
res.redirect(response);
}).catch((error) => console.log(JSON.stringify(error)));
});
app.get('/logout', (req, res) => {
res.redirect('https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000/');
});
app.get('/redirect', (req, res) => {
const tokenRequest = {
code: req.query.code,
scopes: ["user.read"],
redirectUri: "http://localhost:3000/redirect",
};
pca.acquireTokenByCode(tokenRequest).then((response) => {
console.log("\nResponse: \n:", response);
res.sendStatus(200);
}).catch((error) => {
console.log(error);
res.status(500).send(error);
});
});
app.listen(SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port ${SERVER_PORT}!`))
But how to properly check after that logging in if the token is still valid?
So the question is, how can I be save that the user on /dashboard has still a valid token or is logged in?
app.get('/dashboard', (req, res) => {
// check here for valid token...
});
At the end I need a node.js application that:
Can I do all that in node.js or better doing that in client-side? But am I then reducing the security?
Upvotes: 1
Views: 1876
Reputation: 3833
Using the silent-flow was a good idea. It works great on my example.
This works with the PublicClientApplication
and acquireTokenSilent
works also as expected.
Upvotes: 0
Reputation: 3833
I found a kind of dirty way to solve my issue. Could you maybe tell me if that is a proper way? Also my solution is not safe as the user could change the client-side JS code and ignore the user auth.
Create HTML file for /dashboard
:
app.get('/dashboard', function(req, res) {
res.sendFile(__dirname + "/" + "index.html");
});
and here using this JS code:
var headers = new Headers();
var bearer = "Bearer " + "ey...........Ac"; // <---- accessToken
headers.append("Authorization", bearer);
var options = {
method: "GET",
headers: headers
};
var graphEndpoint = "https://graph.microsoft.com/v1.0/me";
fetch(graphEndpoint, options)
.then(resp => {
// when error redirect to ... otherwise do log:
console.log(123);
});
on the <---- accessToken
putting a valid token and it works. Only when token is valid the console.log is done.
So this works, but as I said, if the user is manipulating the code he can still see the page. Also the page is loading until the script is fired. So I cannot see a real value on this. This should happen on server-side somehow. Any idea?
Upvotes: 0
Reputation: 836
Once you get your authentication result the first time, this should have received tokens if authentication was successful. You should be able to parse the Id token to get information about the user. You can then use that information to create a session via the web framework that you are using. The session can be used thorough out the web app to give you information like if the user is authenticated or not, how long they are authenticated for, and what they have permission to access. Usually web frameworks will create a cookie with a session id so that requests coming in will be able to have session information, and the user won't have to authenticate every time.
If the session expires, you can try acquiring a token silently (without prompting the user) by using the token cache that is part of MSAL. When you call acquire token silent, MSAL will automatically check if the access token is valid, if not it will try to refresh the access token via the refresh token. If neither are valid, they will return an error. At this point you can fall back to prompting the user again to authenticate (via the code that you have already shared).
Upvotes: 1