Okta Auth JavaScript SDK 构建在我们的身份验证 API 和 OpenID Connect 和 OAuth 2.0 API 之上,使您能够使用 JavaScript 创建完全品牌化的登录体验。
您可以在我们文档中的 Okta + JavaScript 页面上了解更多信息。
该库使用语义版本控制并遵循 Okta 的库版本策略。
️ ️ ️ ️ ️ ️ ️ ️ ️
️ ️ ️ ️ ️ ️ ️ ️ ️
✔️当前稳定的主要版本系列是: 7.x
版本 | 地位 |
---|---|
7.x | ✔️稳定 |
6.x | 退休 |
5.x | 退休 |
4.x | 退休 |
3.x | 退休 |
2.x | 退休 |
1.x | 退休 |
0.x | 退休 |
最新版本始终可以在版本页面上找到。
如果您在使用 SDK 时遇到问题,您可以:
从此 SDK 的早期版本迁移的用户应参阅迁移指南以了解需要进行哪些更改。
据了解,该 SDK 可与桌面和移动设备上当前版本的 Chrome、Firefox 和 Safari 配合使用。
与 IE 11 / Edge 的兼容性可以通过为以下对象添加 polyfill/shims 来实现:
️ 加密填充无法使用操作系统作为高质量熵的来源,用于生成伪随机数,而伪随机数是良好密码学的关键。因此,我们认为加密填充的安全性较低,建议不要使用它们。
该模块提供了一个实现所有必需的 polyfill 的入口点。
如果您通过浏览器在网页上使用 JS,则可以将node_modules/@okta/okta-auth-js/dist
内容复制到公共托管目录,并包含对okta-auth-js.polyfill.js
文件中的<script>
标记。它应该在任何其他依赖于 polyfill 的脚本之前加载。
如果您使用的是 Webpack 或 Browserify 之类的捆绑程序,则只需在应用程序代码的开头或附近导入 import 或 require @okta/okta-auth-js/polyfill
即可:
import '@okta/okta-auth-js/polyfill' ;
或者
require ( '@okta/okta-auth-js/polyfill' ) ;
构建的 polyfill 包也可以在我们的全球 CDN 上获取。在 HTML 文件中包含以下脚本,以便在任何其他脚本之前加载:
< script src =" https://global.oktacdn.com/okta-auth-js/7.5.1/okta-auth-js.polyfill.js " type =" text/javascript " integrity =" sha384-EBFsuVdi4TGp/DwS7b+t+wA8zmWK10omkX05ZjJWQhzWuW31t7FWEGOnHQeIr8+L " crossorigin =" anonymous " > </ script >
️ 此示例中显示的版本可能比当前版本旧。我们建议使用可用的最高版本
许多浏览器已开始默认阻止跨域或“第三方”cookie。尽管此 SDK 支持的大多数 Okta API 不依赖于 cookie,但有一些方法依赖于 cookie。如果第三方 cookie 被阻止,这些方法将会中断:
如果您的应用程序依赖于这些方法中的任何一种,您应该尝试重写您的应用程序以避免使用这些方法,或者告知您的用户他们必须启用第三方 cookie。 Okta 工程师目前正在研究更好的长期解决方案来解决这个问题。
安装身份验证 SDK 很简单。您可以通过我们的 npm 包 @okta/okta-auth-js 将其包含在您的项目中。
您还需要:
创建新的 Okta 应用程序时,您可以指定应用程序类型。该 SDK 设计用于与SPA
(单页应用程序)或Web
应用程序配合使用。 SPA
应用程序将在客户端执行所有逻辑和授权流程。 Web
应用程序将在服务器上执行授权流程。
在 Okta 管理 UI 中,单击Applications
,然后选择您的应用程序。您可以在应用程序的General
选项卡下查看和编辑 Okta 应用程序的配置。
唯一标识您的 Okta 应用程序的字符串。
为了让用户登录,您的应用程序会将浏览器重定向到 Okta 托管的登录页面。然后,Okta 会重定向回您的应用程序,并提供有关用户的信息。您可以详细了解它如何在 Okta 托管的流上工作。
您需要在 Okta 应用程序设置中将登录重定向 URL 列入白名单。
当您从应用程序和 Okta 中注销用户后,您必须将用户重定向到应用程序中的特定位置。您需要在 Okta 应用程序设置中将注销后 URL 列入白名单。
如果满足以下条件,使用我们的 npm 模块是一个不错的选择:
要安装 @okta/okta-auth-js:
# Run this command in your project root folder.
# yarn
yarn add @okta/okta-auth-js
# npm
npm install --save @okta/okta-auth-js
如果您通过浏览器在网页上使用 JS,则可以将node_modules/@okta/okta-auth-js/dist
内容复制到公共托管目录,并包含对okta-auth-js.min.js
文件中的<script>
标记。
构建的库包也可以在我们的全球 CDN 上获取。在 HTML 文件中包含以下脚本,以便在应用程序脚本之前加载:
< script src =" https://global.oktacdn.com/okta-auth-js/7.5.1/okta-auth-js.min.js " type =" text/javascript " integrity =" sha384-6epSwnIDkI5zFNEVNjEYy3A7aSZ+C7ehmEyG8zDJZfP9Bmnxc51TK8du+2me4pjb " crossorigin =" anonymous " > </ script >
️ 此示例中显示的版本可能比当前版本旧。我们建议使用可用的最高版本
然后,您可以创建全局可用的OktaAuth
对象的实例。
const oktaAuth = new OktaAuth ( {
// config
} )
但是,如果您使用 Webpack 或 Rollup 等捆绑程序,则只需导入或需要该模块即可。
// ES module
import { OktaAuth } from '@okta/okta-auth-js'
const authClient = new OktaAuth ( /* configOptions */ )
// CommonJS
var OktaAuth = require ( '@okta/okta-auth-js' ) . OktaAuth ;
var authClient = new OktaAuth ( /* configOptions */ ) ;
有关客户端功能和身份验证流程的概述,请查看我们的开发人员文档。在那里,您将学习如何在简单的静态页面上使用 Auth SDK 来:
️ 开发人员文档可能是针对该库的早期版本编写的。请参阅从以前的版本迁移。
您还可以浏览完整的 API 参考文档。
⌛ 异步方法返回一个承诺,该承诺将在成功时解决。如果发生错误,Promise 可能会被拒绝。
var config = {
issuer : 'https://{yourOktaDomain}/oauth2/default' ,
clientId : 'GHtf9iJdr60A9IYrR0jw' ,
redirectUri : 'https://acme.com/oauth2/callback/home' ,
} ;
var authClient = new OktaAuth ( config ) ;
默认情况下,创建OktaAuth
的新实例不会产生任何异步副作用。但是,某些功能(例如令牌自动续订、令牌自动删除和跨表同步)需要OktaAuth
作为服务运行。这意味着在后台设置超时,它将继续工作,直到服务停止。要启动OktaAuth
服务,只需在创建后、调用其他方法(如 handleRedirect)之前调用start
方法即可。要终止所有后台进程,请调用stop
。有关详细信息,请参阅服务配置。
var authClient = new OktaAuth ( config ) ;
await authClient . start ( ) ; // start the service
await authClient . stop ( ) ; // stop the service
注意:启动服务也会调用authStateManager.updateAuthState。
类型定义是通过package.json
中的types
条目隐式提供的。类型也可以通过导入来显式引用。
import {
OktaAuth ,
OktaAuthOptions ,
TokenManagerInterface ,
AccessToken ,
IDToken ,
UserClaims ,
TokenParams
} from '@okta/okta-auth-js' ;
const config : OktaAuthOptions = {
issuer : 'https://{yourOktaDomain}'
} ;
const authClient : OktaAuth = new OktaAuth ( config ) ;
const tokenManager : TokenManagerInterface = authClient . tokenManager ;
const accessToken : AccessToken = await tokenManager . get ( 'accessToken' ) as AccessToken ;
const idToken : IDToken = await tokenManager . get ( 'idToken' ) as IDToken ;
const userInfo : UserClaims = await authClient . token . getUserInfo ( accessToken , idToken ) ;
if ( ! userInfo ) {
const tokenParams : TokenParams = {
scopes : [ 'openid' , 'email' , 'custom_scope' ] ,
} ;
authClient . token . getWithRedirect ( tokenParams ) ;
}
3.6 之前的 Typescript 版本没有 WebAuthn 的类型定义。 @okta/[email protected]
中引入了 IDX API 中对 WebAuthn 的支持。要解决此问题,请安装包@types/webappsec-credential-management
version ^0.5.1
。
Web 和本机客户端可以使用authorization_code
流获取令牌,该流使用存储在安全位置的客户端密钥。 (SPA 应用程序应使用不使用客户端密钥的PKCE
流)要使用authorization_code
流,请将responseType
设置为"code"
并将pkce
设置为false
:
var config = {
// Required config
issuer : 'https://{yourOktaDomain}/oauth2/default' ,
clientId : 'GHtf9iJdr60A9IYrR0jw' ,
redirectUri : 'https://acme.com/oauth2/callback/home' ,
// Use authorization_code flow
responseType : 'code' ,
pkce : false
} ;
var authClient = new OktaAuth ( config ) ;
默认情况下将使用 PKCE OAuth 流程。该库支持浏览器和 NodeJS 应用程序的 PKCE。在 HTTPS 连接上运行时,大多数现代浏览器都广泛支持 PKCE。 PKCE 要求浏览器实现crypto.subtle
(也称为webcrypto
)。大多数现代浏览器在安全上下文中(在 HTTPS 连接上)运行时都会提供此功能。 PKCE 还需要 TextEncoder 对象。除 IE 11 和 Edge < v79 之外,所有主要浏览器均可用。为了添加支持,我们建议使用 polyfill/shim,例如文本编码。
如果用户的浏览器不支持PKCE,则会抛出异常。您可以在构建之前使用以下静态方法测试浏览器是否支持 PKCE:
OktaAuth.features.isPKCESupported()
️ 我们强烈反对使用隐式流程。如果可能,请使用 PKCE 和/或客户端凭据。
如果您的部署中不支持 PKCE 流,则可以选择隐式 OAuth 流。它受到大多数浏览器的广泛支持,并且可以在不安全的 HTTP 连接上工作。请注意,隐式流的安全性低于 PKCE 流,即使通过 HTTPS 也是如此,因为原始令牌会在浏览器的历史记录中公开。因此,如果可能的话,我们强烈建议使用 PKCE 流程。
可以通过将pkce
选项设置为false
来启用隐式流
var config = {
pkce : false ,
// other config
issuer : 'https://{yourOktaDomain}/oauth2/default' ,
} ;
var authClient = new OktaAuth ( config ) ;
要登录用户,您的应用程序必须将浏览器重定向到 Okta 托管的登录页面。
注意:初始重定向到 Okta 托管的登录页面会启动一个事务,并将 stateToken 生命周期设置为一小时。
身份验证成功后,浏览器将重定向回您的应用程序以及有关用户的信息。根据您的喜好,可以使用以下回调策略。
大多数应用程序将使用与登录页面分开的特殊路由/页面来处理 OAuth 回调。然而,一些 SPA 应用程序没有路由逻辑,并且希望在单个页面中处理所有内容。
async function main ( ) {
// create OktaAuth instance
var config = {
issuer : 'https://{yourOktaDomain}/oauth2/default' ,
clientId : 'GHtf9iJdr60A9IYrR0jw' ,
redirectUri : 'https://acme.com/oauth2/callback/home' ,
} ;
authClient = new OktaAuth ( config ) ;
// Subscribe to authState change event.
authClient . authStateManager . subscribe ( function ( authState ) {
// Logic based on authState is done here.
if ( ! authState . isAuthenticated ) {
// render unathenticated view
return ;
}
// Render authenticated view
} ) ;
// Handle callback
if ( authClient . token . isLoginRedirect ( ) ) {
const { tokens } = await authClient . token . parseFromUrl ( ) ; // remember to "await" this async call
authClient . tokenManager . setTokens ( tokens ) ;
}
// normal app startup
authClient . start ( ) ; // will update auth state and call event listeners
}
根据 OAuth 2.0 规范,重定向 URI“不得包含片段组件”:https://tools.ietf.org/html/rfc6749#section-3.1.2 当使用哈希/片段路由策略和 OAuth 2.0 时,重定向回调将是主要/默认路由。重定向回调流程与处理没有路由的回调非常相似。我们建议在任何其他授权检查之前定义在应用程序一开始解析重定向 URL 的逻辑。
此外,如果使用哈希路由,我们建议使用 PKCE 和 responseMode“query”(这是 PKCE 的默认设置)。对于隐式流,哈希中的令牌可能会导致不可预测的结果,因为哈希路由器可能会重写片段。
TokenManager
: tokenManager.setTokens参考:DPoP(演示所有权证明)- RFC9449
DPoP
(指南:配置 DPoP)https
。 WebCrypto.subtle
需要安全上下文IndexedDB
(MDN、caniuse) const config = {
// other configurations
pkce : true , // required
dpop : true ,
} ;
const authClient = new OktaAuth ( config ) ;
参考: DPoP 身份验证方案(RFC9449)
GET /protectedresource HTTP/1.1
Host: resource.example.org
Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsIm...
async function dpopAuthenticatedFetch ( url , options ) {
const { method } = options ;
const dpop = await authClient . getDPoPAuthorizationHeaders ( { url , method } ) ;
// dpop = { Authorization: "DPoP token****", Dpop: "proof****" }
const headers = new Headers ( { ... options . headers , ... dpop } ) ;
return fetch ( url , { ... options , headers } ) ;
}
use_dpop_nonce
参考:资源服务器提供的随机数(RFC9449)
资源服务器还可以选择提供一个随机数值,将其包含在发送给它们的 DPoP 证明中。他们使用 DPoP-Nonce 标头提供随机数,就像授权服务器一样......
HTTP/1.1 401 Unauthorized
WWW-Authenticate: DPoP error="use_dpop_nonce",
error_description="Resource server requires nonce in DPoP proof"
DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v
async function dpopAuthenticatedFetch ( url , options ) {
// ...previous example...
const resp = await fetch ( url , { ... options , headers } ) ;
// resp = HTTP/1.1 401 Unauthorized...
if ( ! resp . ok ) {
const nonce = authClient . parseUseDPoPNonceError ( resp . headers ) ;
if ( nonce ) {
const retryDpop = await authClient . getDPoPAuthorizationHeaders ( { url , method , nonce } ) ;
const retryHeaders = new Headers ( { ... options . headers , ... retryDpop } ) ;
return fetch ( url , { ... options , headers : retryHeaders } ) ;
}
}
return resp ;
}
DPoP 需要某些浏览器功能。使用不具备所需功能的浏览器的用户将无法完成令牌请求。建议在应用程序引导期间验证浏览器支持。
// App.tsx
useEffect ( ( ) => {
if ( ! authClient . features . isDPoPSupported ( ) ) {
// user will be unable to request tokens
navigate ( '/unsupported-error-page' ) ;
}
} , [ ] ) ;
DPoP 需要生成需要持久保存在存储中的CryptoKeyPair
。像signOut()
或revokeAccessToken()
这样的方法将清除密钥对,但是用户并不总是显式注销。因此,最好在登录之前清除存储,以刷新从先前请求的令牌生成的任何孤立密钥对。
async function login ( options ) {
await authClient . clearDPoPStorage ( ) ; // clear possibly orphaned key pairs
return authClient . signInWithRedirect ( options ) ;
}
无论您是使用此 SDK 实现 OIDC 流程还是与身份验证 API 进行通信,唯一需要的配置选项是issuer
,它是 Okta 授权服务器的 URL
您可以使用 Okta 组织的 URL 作为发行者。这将应用默认授权策略并颁发组织级别范围内的令牌。
var config = {
issuer : 'https://{yourOktaDomain}'
} ;
var authClient = new OktaAuth ( config ) ;
Okta 允许您创建多个自定义 OAuth 2.0 授权服务器,您可以使用它们来保护您自己的资源服务器。在每个授权服务器中,您可以定义自己的 OAuth 2.0 范围、声明和访问策略。许多组织都有一个“默认”授权服务器。
var config = {
issuer : 'https://{yourOktaDomain}/oauth2/default'
} ;
var authClient = new OktaAuth ( config ) ;
您还可以创建和自定义其他授权服务器。
var config = {
issuer : 'https://{yourOktaDomain}/oauth2/custom-auth-server-id'
} ;
var authClient = new OktaAuth ( config ) ;
实例化 Okta Auth JS ( new OktaAuth(config)
) 时可以包含这些选项。
issuer
️ 该选项为必填项
您的 Okta 组织或 Okta 身份验证服务器的 URL。关于发行人
clientId
已向 Okta 预先注册 OIDC 身份验证流程的客户端 ID。创建您的 Okta 应用程序
redirectUri
使用token.getWithRedirect
时重定向到的 url。这必须列在您的 Okta 应用程序的登录重定向 URI 中。如果未提供redirectUri
,则默认为当前原点( window.location.origin
)。配置您的 Okta 应用程序
postLogoutRedirectUri
指定退出后浏览器应重定向到的 URL。此 URL 必须列在您的 Okta 应用程序的注销重定向 URI 中。如果未指定,将使用应用程序的原点 ( window.location.origin
)。配置您的 Okta 应用程序 |
scopes
指定在返回的id_token
或access_token
中提供哪些信息。对于 OIDC,您必须将openid
包含为范围之一。默认为['openid', 'email']
。有关可用范围的列表,请参阅范围和声明
state
客户端提供的字符串,将传递到服务器端点并在 OAuth 响应中返回。该值可用于验证 OAuth 响应并防止跨站点请求伪造 (CSRF)。默认为随机字符串。
pkce
默认值为true
,这将启用 PKCE OAuth 流程。要使用隐式流或授权代码流,请将pkce
设置为false
。
dpop
默认值为false
。设置为true
以启用DPoP
(演示所有权证明 (RFC9449))
请参阅指南:启用 DPoP
当使用 token.getWithRedirect 请求令牌时,值将作为附加到redirectUri 的参数返回。
在大多数情况下,您不需要为responseMode
设置值。默认值根据 OpenID Connect 1.0 规范设置。
对于 PKCE OAuth Flow),授权代码将位于 URL 的搜索查询中。使用 PKCE 流的客户端可以选择通过将 responseMode 选项设置为“fragment”来接收哈希片段中的授权代码。
对于隐式 OAuth 流),令牌将位于 URL 的哈希片段中。这是无法改变的。
responseType
使用隐式 OAuth 流程时指定 OIDC 身份验证的响应类型。默认值为['token', 'id_token']
它将请求访问令牌和 ID 令牌。如果pkce
为true
,则将请求访问令牌和 ID 令牌,并且将忽略此选项。对于使用authorization_code
流程的Web/本机应用程序,该值应设置为"code"
, pkce
应设置为false
。
authorizeUrl
指定自定义authorizeUrl来执行OIDC流程。默认为颁发者加“/v1/authorize”。
userinfoUrl
指定自定义 userinfoUrl。默认为颁发者加“/v1/userinfo”。
tokenUrl
指定自定义 tokenUrl。默认为发行者加“/v1/token”。
ignoreSignature
️ 此选项应仅用于浏览器支持和测试目的。
默认情况下,当调用token.getWithoutPrompt
、 token.getWithPopup
、 token.getWithRedirect
和token.verify
时,会验证 ID 令牌签名。要禁用这些方法的 ID 令牌签名验证,请将此值设置为true
。
maxClockSkew
默认为 300(五分钟)。这是验证令牌时客户端时钟与 Okta 时钟之间允许的最大差异(以秒为单位)。不建议将此值设置为 0,因为它会增加有效令牌验证失败的可能性。
ignoreLifetime
️ 此选项禁用令牌生命周期验证,这可能会引入安全漏洞问题。该选项应用于测试目的。请在您自己的生产环境应用程序中处理错误。
令牌生命周期使用 maxClockSkew 进行验证。要覆盖此设置并禁用令牌生命周期验证,请将此值设置为true
。
transformAuthState
回调函数。当调用 updateAuthState 时,会生成一个新的 authState 对象。提供transformAuthState
函数允许您在存储和发出该对象之前修改或替换该对象。一个常见的用例是更改 isAuthenticated 的含义。默认情况下,如果 tokenManager 中有未过期的令牌,则updateAuthState
会将authState.isAuthenticated
设置为 true。可以自定义此逻辑以还需要有效的 Okta SSO 会话:
const config = {
// other config
transformAuthState : async ( oktaAuth , authState ) => {
if ( ! authState . isAuthenticated ) {
return authState ;
}
// extra requirement: user must have valid Okta SSO session
const