We successfully integrated a static frontend application to connect to a Spring-Based backend API using JWT Tokens with https://github.com/IdentityModel/oidc-client-js.
var userManager = new Oidc.UserManager({
authority: 'https://openid-connect-eu.onelogin.com/oidc',
client_id: config.oidc_client_id,
redirect_uri: config.oidc_redirect_uri,
response_type: 'id_token token',
scope: 'openid profile email',
filterProtocolClaims: true,
loadUserInfo: true
});
var user = {};
async function _login() {
user = await userManager.getUser();
if (!user || user.expired) {
var hash = parseUrl(window.location.hash),
id_token = hash.id_token;
if (id_token) {
user = await userManager.signinRedirectCallback();
initAfterLogin(user);
} else {
userManager.signinRedirect();
}
}
else {
initAfterLogin();
}
}
function initAfterLogin() {
console.log('JWT Token: ', user.id_token)
}
We kan use the JWT Token as Bearer authentication call for our backend, and the validation succeeds.
Now, we're trying to find a way to automatically test our backend calls, so we need to get the JWT token from a NodeJS runtime (POSTman Pre-Request Script).
const getJwtTokenRequest = {
url: 'https://openid-connect-eu.onelogin.com/oidc/token',
method: 'POST',
header: [{
key: 'Content-Type',
value: 'application/x-www-form-urlencoded'
},{
key: 'Authorization',
value: 'Basic '+Buffer.from(client_id+':'+client_secret).toString('base64')
}
],
body: {
mode: 'urlencoded',
urlencoded: [{
key: 'username',
value: test_user
}, {
key: 'password',
value: test_password
}, {
key: 'client_id',
value: client_id
}, {
key: 'grant_type',
value: 'password'
}, {
key: 'scope',
value: 'openid profile email'
}, {
key: 'response_type',
value: 'id_token token'
}
]
}
};
var getToken = true;
if (!pm.environment.get('OIDC_JWT_Token') ||
!pm.environment.get('OIDC_JWT_Expiry')) {
console.log('Token or expiry date are missing')
} else if (pm.environment.get('OIDC_JWT_Expiry') <= (new Date()).getTime()) {
console.log('Token is expired')
} else {
getToken = false;
console.log('Token and expiry date are all good');
}
if (getToken === true) {
pm.sendRequest(getJwtTokenRequest, function (err, res) {
console.log(err ? err : res.json());
if (err === null) {
console.log('Saving the token and expiry date')
var responseJson = res.json();
pm.environment.set('OIDC_JWT_Token', responseJson.id_token)
var expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
pm.environment.set('OIDC_JWT_Expiry', expiryDate.getTime());
}
});
}
However, the /token api endpoint only returns an access_token, not an id_token (JWT token).
{
"access_token": "MzEzNzJlMmYtZmFhMS00MXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-fn7fOiqgao-EiPp-PKrtMHqnBafdtbKU-DpodVl9YQqTwxDNTgE0k6w",
"expires_in": 3600,
"token_type": "Bearer"
}
If I search through the OneLogin API, it seams that we can only get the id_token from an explicit authorization flow via the frontend.
Only being able to get an id_token
from an explicit authorization flow is typically the case since the id_token
represents a user authentication event and as such the user should be present.
There may be a way to use the Resource Owner Password Credentials grant type to do the same in a non-browser scenario but that depends on the features that OneLogin provides.
If they do you'd have to request the token using grant_type=password
and provide scope=openid
.