I'm using auth0 to authenticate my logins to my Single Page App (built on React). I'm mostly using the base API calls (listed here).
The process I'm using is:
get username/email and password when the user enters them on my app's login page
Send a POST request to /oauth/ro with those values - here is that code:
export const login = (params, err) => {
if (err) return err
const {email, password} = params
const {AUTH0_CLIENT_ID, AUTH0_DOMAIN} = process.env
return fetch(`${AUTH0_DOMAIN}/oauth/ro`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'client_id': AUTH0_CLIENT_ID,
'username': email,
'password': password,
'connection': 'Username-Password-Authentication',
'grant_type': 'password',
'scope': 'openid',
'device': '',
'id_token': ''
})
})
.then(response => response.json())
.then(json => {
const {id_token, access_token} = json
setCookieValue('id_token', id_token) // utility function I wrote
return getProfile(access_token)
.then(data => {
const {user_id, email: emailAddress, picture, name} = data
return {id_token, user_id, emailAddress, picture, name}
})
})
.catch(error => console.log(`ERROR: ${error}`))
}
This is all sent through Redux and the user is logged in (assuming the username/password was correct).
However, I'm trying to figure out how to persist the login when refreshing the page/coming back to the app. I'm saving the id_token (which is a JWT) in the browser's cookies and can fetch this when the app renders server-side. I can decode the JWT and get the payload (sub is the user ID from auth0). However, to get the profile data I need the access_token which Auth0 provides when using the /oauth/ro POST request. Obviously, if the JWT token has expired then it will just reject it and keep the user logged out.
Here is my code to decode the JWT (happens on app render):
const ID_TOKEN = req.cookies.id_token || false
if (ID_TOKEN) {
verifyJwt(ID_TOKEN, (err, decoded) => {
if (err) { console.log(`JWT Verification error: ${err}`) }
else {
const {sub} = decoded
getProfile(sub).then(data => store.dispatch(fetchUserDetails(data))) // fails as `sub` (the user id) is not the `access_token` which it requires
}
})
}
I have tried using the /oauth/ro call again, but this time specifying "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer" and using the id_token retrieved from the cookies, and specifying a device. However, when I do this call, I get this error from Auth0:
{
"error": "invalid_request",
"error_description": "there is not an associated public key for specified client_id/user_id/device"
}
So my question is, what API call do I need to make to get the access_token from the id_token JWT?
Also, as a bonus - when I do the POST request to login, the password is being transfered over plaintext. How would I encrypt this when sending to auth0 so they can decrypt it back? I assume it involves using the client_secret which auth0 provide but I'm not sure how to go about doing that.