Using the Proxy SDK to Authenticate a User
The Proxy SDK creates and manages transactions for when a user needs to perform initial login and subsequent multi-factor authentication(MFA), helping manage state across requests.
When integrating with the Proxy SDK, there are three types of responses which may need to be handled:
- Allow
- Deny
- Require
Note: The Allow response is never returned prior to initial authentication being successful.
These three responses allow for building a workflow like:
- User initiates login
- User may not be able to authenticate at this time. IE Banned country being used to access application
- User may have to authenticate with a strong factor - User prompted for appropriate login
- User performs login successfully - Adaptive risk assessment performed
- User may need to provide further authentication factors
- User may be allowed to access without MFA due to low evaluated risk score
- User may be denied access due to high evaluated risk score
Depending on the UX required in the application, there are two approaches which can be taken:
- Have a login page which both performs both collection and initial authentication all at once.
- Have a page which performs collection and initiates an assessment before the login page is made available
- You would use this style of page when the pre-authentication rules may render a different experience depending on context
- e.g. If a login page forfido2
should be used in some situations, or if there are instances where adeny
would be returned
This example follows an approach where the policy assessment and invocation of the username/password authentication mechanism occurs within the same request.
// add session awareness
const session = require('express-session')
// add body parsing
const bodyParser = require('body-parser');
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
}))
// Add url form-encoded middleware to process login form
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/login", (req, res) => {
// Extract parameters from request.
const username = req.body.username;
const password = req.body.password;
var context = {
sessionId : req.body.sessionId, // The session ID generated posted from the browser
userAgent : req.headers['user-agent'], // The user-agent collected from headers
ipAddress : req.ip // The IP address of the connection.
};
// Which identity source to use for username/password login.
// You can discover available identity sources using:
// https://myidp.ice.ibmcloud.com/developer/explorer/#/Identity_Sources
const identitySourceId = '6c0e1e52-06f9-4a47-bbd5-089f3498220e';
// Perform a risk assessment.
adaptive.assessPolicy(context)
.then((result) => {
if (result.status == "deny") {
res.status(403).send({ error: "Denied" });
return
}
// Store the sessionState:
req.session.transactionId = result.transactionId
req.session.sessionId = context.sessionId
if(result.allowedFactors.indexOf("password") != -1) {
adaptive.evaluatePassword(context, result.transactionId, identitySourceId, username, password)
.then((result) => {
if (result.status == "deny") {
res.status(403).send({ error: "Denied" });
return
}
if (result.status == "allow") {
req.session.token = result.token;
res.redirect("/");
return
}
}).catch((error) => {
console.log(error);
if (error.response.data.messageDescription) {
res.status(403).send({ error: error.response.data.messageDescription });
} else {
res.status(403).send({ error: "Password check failed" });
}
});
} else {
res.status(403).send({ error: "Password login not allowed" });
}
});
});
Note: Establish the adaptive
object using the initialization steps in Adding the Proxy SDK to an application server
Next: Performing MFA
Previous: Adding the Proxy SDK to an Application Server
See also: Proxy SDK API documentation