从现有 id_token 获取 Auth0 access_token
Get Auth0 access_token from existing id_token
我正在使用 auth0 to authenticate my logins to my Single Page App (built on React). I'm mostly using the base API calls (listed here).
我使用的流程是:
当用户在我的应用程序的登录页面上输入它们时获得 username/email 和密码
使用这些值向 /oauth/ro
发送 POST 请求 - 这是代码:
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}`))
}
这都是通过 Redux 发送的,并且用户已登录(假设 username/password 是正确的)。
但是,我正在尝试弄清楚如何在将 page/coming 刷新回应用程序时保持登录。我将 id_token
(这是一个 JWT)保存在浏览器的 cookie 中,并且可以在应用程序呈现服务器端时获取它。我可以解码 JWT 并获取有效负载(sub
是来自 auth0 的用户 ID)。但是,要获取配置文件数据,我需要 Auth0 在使用 /oauth/ro
POST 请求时提供的 access_token
。显然,如果 JWT 令牌已过期,那么它只会拒绝它并让用户退出。
这是我解码 JWT 的代码(发生在应用程序渲染上):
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
}
})
}
我尝试再次使用 /oauth/ro
调用,但这次指定 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer"
并使用从 cookie 检索的 id_token
,并指定 device
。但是,当我执行此调用时,我从 Auth0 收到此错误:
{
"error": "invalid_request",
"error_description": "there is not an associated public key for specified client_id/user_id/device"
}
所以我的问题是,我需要调用什么 API 才能从 id_token
JWT 获取 access_token
?
此外,作为奖励 - 当我执行 POST 登录请求时,password
正在通过明文传输。发送到 auth0 时我将如何加密它以便他们可以解密它?我认为它涉及使用 auth0 提供的 client_secret
,但我不确定如何去做。
无需任何类型的用户交互即可以编程方式刷新令牌的能力是通过使用 refresh tokens 实现的。但是,这不适用于基于浏览器的应用程序,因为刷新令牌是长期有效的凭据,浏览器的存储特性会使它们面临更大的泄露风险。
如果您想继续使用资源所有者密码凭据授权,您可以选择在令牌过期时要求用户再次输入凭据。作为替代方案,在进行身份验证后,您可以获得所需的用户信息并启动特定于应用程序的会话。这可以通过让您的服务器端逻辑创建应用程序特定会话标识符或 JWT 来实现。
您也可以停止使用资源所有者密码凭据授予并将用户重定向到 Auth0 身份验证页面,除了将令牌返回到您的应用程序之外,还会为用户维护经过身份验证的会话,这意味着当令牌过期并且您的应用程序再次重定向到 Auth0,用户可能不需要手动重新输入凭据,因为 Auth0 会话仍然有效。
关于以明文形式发送的密码;资源所有者端点依赖 HTTPS,因此数据在协议级别加密。您还必须在自己的应用程序中使用 HTTPS 进行任何类型的通信,包括任何类型的用户凭据。
另请注意,您可以通过使用范围来控制 ID 令牌中返回的内容,具体取决于相关信息量,如果您 signal that you want that information to be contained within the ID token itself.
我正在使用 auth0 to authenticate my logins to my Single Page App (built on React). I'm mostly using the base API calls (listed here).
我使用的流程是:
当用户在我的应用程序的登录页面上输入它们时获得 username/email 和密码
使用这些值向 /oauth/ro
发送 POST 请求 - 这是代码:
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}`))
}
这都是通过 Redux 发送的,并且用户已登录(假设 username/password 是正确的)。
但是,我正在尝试弄清楚如何在将 page/coming 刷新回应用程序时保持登录。我将 id_token
(这是一个 JWT)保存在浏览器的 cookie 中,并且可以在应用程序呈现服务器端时获取它。我可以解码 JWT 并获取有效负载(sub
是来自 auth0 的用户 ID)。但是,要获取配置文件数据,我需要 Auth0 在使用 /oauth/ro
POST 请求时提供的 access_token
。显然,如果 JWT 令牌已过期,那么它只会拒绝它并让用户退出。
这是我解码 JWT 的代码(发生在应用程序渲染上):
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
}
})
}
我尝试再次使用 /oauth/ro
调用,但这次指定 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer"
并使用从 cookie 检索的 id_token
,并指定 device
。但是,当我执行此调用时,我从 Auth0 收到此错误:
{
"error": "invalid_request",
"error_description": "there is not an associated public key for specified client_id/user_id/device"
}
所以我的问题是,我需要调用什么 API 才能从 id_token
JWT 获取 access_token
?
此外,作为奖励 - 当我执行 POST 登录请求时,password
正在通过明文传输。发送到 auth0 时我将如何加密它以便他们可以解密它?我认为它涉及使用 auth0 提供的 client_secret
,但我不确定如何去做。
无需任何类型的用户交互即可以编程方式刷新令牌的能力是通过使用 refresh tokens 实现的。但是,这不适用于基于浏览器的应用程序,因为刷新令牌是长期有效的凭据,浏览器的存储特性会使它们面临更大的泄露风险。
如果您想继续使用资源所有者密码凭据授权,您可以选择在令牌过期时要求用户再次输入凭据。作为替代方案,在进行身份验证后,您可以获得所需的用户信息并启动特定于应用程序的会话。这可以通过让您的服务器端逻辑创建应用程序特定会话标识符或 JWT 来实现。
您也可以停止使用资源所有者密码凭据授予并将用户重定向到 Auth0 身份验证页面,除了将令牌返回到您的应用程序之外,还会为用户维护经过身份验证的会话,这意味着当令牌过期并且您的应用程序再次重定向到 Auth0,用户可能不需要手动重新输入凭据,因为 Auth0 会话仍然有效。
关于以明文形式发送的密码;资源所有者端点依赖 HTTPS,因此数据在协议级别加密。您还必须在自己的应用程序中使用 HTTPS 进行任何类型的通信,包括任何类型的用户凭据。
另请注意,您可以通过使用范围来控制 ID 令牌中返回的内容,具体取决于相关信息量,如果您 signal that you want that information to be contained within the ID token itself.