从现有的id_token获取Auth0 access_token

时间:2016-11-21 14:29:33

标签: javascript oauth jwt auth0

我正在使用auth0来验证我的单页应用程序(基于React构建)的登录。我主要使用基本API调用(列出here)。

我正在使用的流程是:

当用户在我的应用程序的登录页面上输入用户名/电子邮件和密码时 使用这些值向/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发送的,并且用户已登录(假设用户名/密码正确无误)。

但是,我正在尝试弄清楚如何在刷新页面/返回应用程序时保持登录。我将id_token(这是JWT)保存在浏览器的Cookie中,并且可以在应用呈现服务器端时获取此值。我可以解码JWT并获取有效负载(sub是来自auth0的用户ID)。但是,要获取配置文件数据,我需要使用access_token POST请求时Auth0提供的/oauth/ro。显然,如果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"
}

所以我的问题是,从access_token JWT获取id_token需要进行哪些API调用?

另外,作为奖励 - 当我执行POST登录请求时,password正在通过明文传输。发送到auth0时如何加密,以便他们可以解密?我认为它涉及使用auth0提供的client_secret,但我不知道如何去做。

1 个答案:

答案 0 :(得分:0)

通过使用refresh tokens,无需任何类型的用户交互即可以编程方式刷新令牌。但是,这不适用于基于浏览器的应用程序,因为刷新令牌是长期存在的凭据,浏览器的存储特性会使它们面临更大的泄露风险。

如果要继续使用资源所有者密码凭据授予,您可以选择在令牌过期时要求用户再次输入凭据。作为替代方案,在身份验证时,您可以获取所需的用户信息并启动特定于应用程序的会话。这可以通过让服务器端逻辑创建特定于应用程序的会话标识符或JWT来实现。

您还可以停止使用资源所有者密码凭据grant并将用户重定向到Auth0身份验证页面,除了将令牌返回到您的应用程序之外,还会为用户维护经过身份验证的会话,这意味着当令牌已过期且您的应用程序再次重定向到Auth0,用户可能不需要手动重新输入凭据,因为Auth0会话仍然有效。

关于以明文发送的密码;资源所有者端点依赖于HTTPS,因此数据在协议级别进行加密。您还必须在自己的应用程序中使用HTTPS,以进行包含任何类型的用户凭据的任何类型的通信。

另请注意,您可以通过使用范围来控制ID令牌中返回的内容,具体取决于您可能甚至不需要进行额外调用以获取用户配置文件的信息量{{ {3}}