I’m trying to setup Auth0 with an existing API using spring security. This API works with a single page app front end.
From what I understand I need to use JWT, and add custom claims that will contain my roles inside the JWT.
In order to retrieve the JWT I downloaded the javascript quickstart and modified it slightly to retrieve the access token and provide an audience and the roles scope. This is the content of my app.js:
window.addEventListener('load', function() {
var lock = new Auth0Lock(AUTH0_CLIENT_ID, AUTH0_DOMAIN, {
auth: {
responseType: 'token',
params: {
audience: 'my audience',
scope: 'openid roles'
}}
});
// buttons
var btn_login = document.getElementById('btn-login');
var btn_logout = document.getElementById('btn-logout');
btn_login.addEventListener('click', function() {
lock.show();
});
btn_logout.addEventListener('click', function() {
logout();
});
lock.on("authenticated", function(authResult) {
console.log(authResult.accessToken)
lock.getProfile(authResult.idToken, function(error, profile) {
if (error) {
// Handle error
return;
}
localStorage.setItem('id_token', authResult.idToken);
// Display user information
show_profile_info(profile);
});
});
//retrieve the profile:
var retrieve_profile = function() {
var id_token = localStorage.getItem('id_token');
if (id_token) {
lock.getProfile(id_token, function (err, profile) {
if (err) {
return alert('There was an error getting the profile: ' + err.message);
}
// Display user information
show_profile_info(profile);
});
}
};
var show_profile_info = function(profile) {
var avatar = document.getElementById('avatar');
document.getElementById('nickname').textContent = profile.nickname;
btn_login.style.display = "none";
avatar.src = profile.picture;
avatar.style.display = "block";
btn_logout.style.display = "block";
};
var logout = function() {
localStorage.removeItem('id_token');
window.location.href = "/";
};
retrieve_profile();
});
Using this app I’m able to login properly, but the token that I’m getting doesn’t reflect the roles of the user. (the roles are supposed to be added by a rule)
I’m getting a JWT that has the following:
{
"iss": "https://blabla.auth0.com/",
"sub": "auth0|blabla",
"aud":
"my audience",
"https://blabla.auth0.com/userinfo"
],
"azp": "blabla",
"exp": 1495240761,
"iat": 1495233561,
"scope": "openid roles"
}
I’ve read that it might be because of the OICD specification etc, but not too sure.
Would any of you have recommendations on how I could get the proper JWT to access my API’s endpoints?
Update (follow-up question):
I’m now able to see the roles in my access token:
{
"iss": "https://blabla.auth0.com/",
"sub": "auth0|blabla",
"aud":
"https://api.example.com",
"https://blabla.auth0.com/userinfo"
],
"azp": "something",
"exp": 1495484775,
"iat": 1495477575,
"scope": "openid roles email picture",
"https://api.example.com/roles":
"ROLE_ADMIN"
]
}
However it seems like Spring Security is not able to read those roles.
This is my security config:
@Override
protected void configure(HttpSecurity http) throws Exception {
JwtWebSecurityConfigurer
.forRS256("https://api.example.com", "https://blabla.auth0.com/")
.configure(http)
.headers()
.addHeaderWriter(new CacheControlHeadersWriter())
.addHeaderWriter(new XContentTypeOptionsHeaderWriter())
.addHeaderWriter(new XXssProtectionHeaderWriter())
.and()
.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class)
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/v1/login/**").hasAnyRole("ROLE_ADMIN")
.and()
.httpBasic();
}
It seems like it’s able to authenticate me, but then I get a 403 status code.
I tried to change the rule to change the roles field syntax so it looks like this: "https://api.example.com/roles": "'ROLE_ADMIN']"
but still the same issue.
Here is the code for my rule:
function (user, context, callback) {
var namespace = 'https://api.example.com/';
context.accessToken[namespace + 'roles'] = 'ROLE_ADMIN'];
callback(null, user, context);
}
Any idea?