用于 IBM Cloud App ID 服务的 Swift SDK
此 SDK 提供了用于保护 Web 应用程序和 API 端点的 Kitura Credentials 插件。
当使用 WebAppKituraCredentialsPlugin 时,未经身份验证的客户端将被 HTTP 302 重定向到 App ID 服务托管的登录页面(或者,根据配置,直接重定向到身份提供者登录页面)。
阅读官方文档,了解有关开始使用 IBM Cloud App ID 服务的信息。
import PackageDescription
let package = Package(
...
dependencies: [
.package(url: "https://github.com/ibm-cloud-security/appid-serversdk-swift.git", .upToNextMinor(from: "5.1.0"))
]
.target(
name: "<Your Target>",
dependencies: ["IBMCloudAppID"]
)
)
以下是使用此 SDK 保护 Web 应用程序的示例。
WebAppKituraCredentialsPlugin 基于 OAuth2 authorization_code 授权流程,应供使用浏览器的 Web 应用程序使用。该插件提供了用于轻松实现身份验证和授权流程的工具。 WebAppKituraCredentialsPlugin 提供了检测未经身份验证的访问受保护资源的尝试的机制。 WebAppKituraCredentialsPlugin 将自动将用户的浏览器重定向到身份验证页面。 成功通过身份验证后,用户将被带回到 Web 应用程序的回调 URL (redirectUri),该 URL 将再次使用 WebAppKituraCredentialsPlugin 从 App ID 服务获取访问令牌和身份令牌。 获取这些令牌后,WebAppKituraCredentialsPlugin 会将它们存储在 HTTP 会话的 WebAppKituraCredentialsPlugin.AuthContext 键下。 在可扩展的云环境中,建议将 HTTP 会话持久存储在可扩展的存储(如 Redis)中,以确保它们在多个服务器应用程序实例中可用。
import Kitura
import KituraSession
import Credentials
import SwiftyJSON
import IBMCloudAppID
// Below URLs will be used for App ID OAuth flows
var LOGIN_URL = "/ibm/bluemix/appid/login"
var CALLBACK_URL = "/ibm/bluemix/appid/callback"
var LOGOUT_URL = "/ibm/bluemix/appid/logout"
var LANDING_PAGE_URL = "/index.html"
// Setup Kitura to use session middleware
// Must be configured with proper session storage for production
// environments. See https://github.com/IBM-Swift/Kitura-Session for
// additional documentation
let router = Router()
let session = Session(secret: "Some secret")
router.all(middleware: session)
// Use static resources if required directory
router.all("/", middleware: StaticFileServer(path: "./Tests/IBMCloudAppIDTests/public"))
// Below configuration can be obtained from Service Credentials
// tab in the App ID Dashboard. You're not required to manually provide below
// configuration if your Kitura application runs on IBM Cloud and is bound to the
// App ID service instance. In this case App ID configuration will be obtained
// automatically using VCAP_SERVICES environment variable.
//
// The redirectUri value can be supplied in three ways:
// 1. Manually in new WebAppKituraCredentialsPlugin options
// 2. As environment variable named `redirectUri`
// 3. If none of the above was supplied the App ID SDK will try to retrieve
// application_uri of the application running on IBM Cloud and append a
// default suffix "/ibm/bluemix/appid/callback"
let options = [
"clientId": "{client-id}",
"secret": "{secret}",
"tenantId": "{tenant-id}",
"oauthServerUrl": "{oauth-server-url}",
"redirectUri": "{app-url}" + CALLBACK_URL
]
let webappKituraCredentialsPlugin = WebAppKituraCredentialsPlugin(options: options)
let kituraCredentials = Credentials()
kituraCredentials.register(plugin: webappKituraCredentialsPlugin)
// Explicit login endpoint
router.get(LOGIN_URL,
handler: kituraCredentials.authenticate(credentialsType: webappKituraCredentialsPlugin.name,
successRedirect: LANDING_PAGE_URL,
failureRedirect: LANDING_PAGE_URL
))
// Callback to finish the authorization process. Will retrieve access and identity tokens from App ID
router.get(CALLBACK_URL,
handler: kituraCredentials.authenticate(credentialsType: webappKituraCredentialsPlugin.name,
successRedirect: LANDING_PAGE_URL,
failureRedirect: LANDING_PAGE_URL
))
// Logout endpoint. Clears authentication information from session
router.get(LOGOUT_URL, handler: { (request, response, next) in
kituraCredentials.logOut(request: request)
webappKituraCredentialsPlugin.logout(request: request)
_ = try? response.redirect(LANDING_PAGE_URL)
})
// Protected area using `Credentials` standard `userProfile`
router.get("/protected", handler: kituraCredentials.authenticate(credentialsType: webappKituraCredentialsPlugin.name), { (request, response, next) in
// check user profile for successful login
guard let user = request.userProfile else {
response.status(.unauthorized)
return next()
}
try response.send("Hello \(user.displayName)")
next()
})
// Protected area using AppID `userIdentity`
router.get("/protected", handler: kituraCredentials.authenticate(credentialsType: webappKituraCredentialsPlugin.name), { (request, response, next) in
guard let authContextDict = request.session?["APPID_AUTH_CONTEXT"] as? [String: Any],
let identityTokenPayload = authContextDict["identityTokenPayload"] as? [String: Any],
let identityTokenData = try? JSONSerialization.data(withJSONObject: identityTokenPayload, options: [])
else {
response.status(.unauthorized)
return next()
}
let authContext = AuthorizationContext(idTokenPayload: JSON(data: identityTokenData))
response.send("Hello \(authContext.userIdentity.displayName)")
next()
})
// Start the server!
Kitura.addHTTPServer(onPort: 1234, with: router)
Kitura.run()
APIKituraCredentialsPlugin 遵循 OAuth Bearer Token 规范,应用于保护后端 API 端点。
当您的 Kitura 后端收到请求时,凭证中间件将检查其授权标头中是否存在 Bearer 令牌,然后根据 App ID 公钥集对其进行验证。 成功后,中间件会将授权上下文和用户配置文件添加到请求中,并将其传递给下一个中间件或您的处理程序。 如果未提供身份令牌,则用户配置文件的字段将为空。
import Kitura
import Credentials
import IBMCloudAppID
// Below configuration can be obtained from Service Credentials
// tab in the App ID Dashboard. You're not required to manually provide below
// configuration if your Kitura application runs on IBM Cloud and is bound to the
// App ID service instance. In this case App ID configuration will be obtained
// automatically using VCAP_SERVICES environment variable.
let options = [
"oauthServerUrl": "{oauth-server-url}"
]
let apiCredentials = APIKituraCredentialsPlugin(options: options)
let credentials = Credentials()
credentials.register(plugin: apiCredentials)
// Protected area
router.all(middleware: credentials)
router.get("/myName") { (request, response, next) in
do {
if let userProfile = request.userProfile {
try response.status(.OK).send(userProfile.displayName).end()
}
} catch {
response.status(.internalServerError)
}
}
// Start the server!
Kitura.addHTTPServer(onPort: 8080, with: router)
Kitura.run()
WebAppKituraCredentialsPlugin 允许用户匿名登录到您的 Web 应用程序,这意味着无需任何凭据。 成功登录后,匿名用户访问令牌将保存在 HTTP 会话中,只要 HTTP 会话保持活动状态,该令牌就可用。 一旦 HTTP 会话被销毁或过期,匿名用户访问令牌也将被销毁。
要允许特定 URL 的匿名登录,请使用以下代码片段中所示的两个配置属性
WebAppKituraCredentialsPlugin.AllowAnonymousLogin
- 如果您想允许您的用户在访问此端点时匿名登录,请将此值设置为 true。 如果此属性设置为 true,则无需身份验证。 此属性的默认值为 false
,因此您必须显式设置它以允许匿名登录。WebAppKituraCredentialsPlugin.AllowCreateNewAnonymousUser
- 默认情况下,每次调用此方法时都会创建一个新的匿名用户,除非当前 HTTP 会话中存储了现有的 anonymous access_token。 在某些情况下,您希望显式控制是否要自动创建新的匿名用户。 如果要禁用自动创建新匿名用户,请将此属性设置为 false
。 此属性的默认值为 true
。var LOGIN_ANON_URL = "/ibm/bluemix/appid/loginanon"
let webappKituraCredentialsPlugin = WebAppKituraCredentialsPlugin(options: options)
let kituraCredentialsAnonymous = Credentials(options: [
WebAppKituraCredentialsPlugin.AllowAnonymousLogin: true,
WebAppKituraCredentialsPlugin.AllowCreateNewAnonymousUser: true
])
kituraCredentialsAnonymous.register(plugin: webappKituraCredentialsPlugin)
// Explicit anonymous login endpoint
router.get(LOGIN_ANON_URL,
handler: kituraCredentialsAnonymous.authenticate(credentialsType: webappKituraCredentialsPlugin.name,
successRedirect: LANDING_PAGE_URL,
failureRedirect: LANDING_PAGE_URL
))
router.get(LOGOUT_URL, handler: { (request, response, next) in
kituraCredentialsAnonymous.logOut(request: request)
webappKituraCredentialsPlugin.logout(request: request)
_ = try? response.redirect(LANDING_PAGE_URL)
})
匿名访问令牌和身份令牌由 App ID SDK 自动保存在 HTTP 会话中。 您可以通过与常规令牌相同的机制从 HTTP 会话中检索它们。 访问令牌和身份令牌将保留在 HTTP 会话中,并将一直使用到令牌或 HTTP 会话过期。
使用 App ID UserProfileManager,您可以创建、删除和检索用户个人资料属性,以及获取有关用户的其他信息。
let userProfileManager = UserProfileManager(options: options)
userProfileManager.getAttribute(accessToken: accessToken, attributeName: "name") { (err, res) in
}
userProfileManager.setAttribute(accessToken: accessToken, attributeName: "name", attributeValue : "abc") { (err, res) in
}
userProfileManager.getAllAttributes(accessToken: accessToken) { (err, res) in
}
userProfileManager.deleteAllAttributes(accessToken: accessToken) { (err, res) in
}
// Retrieve user information by querying the UserInfo endpoint
// If identity token is provided (recommended approach), response is validated against the identity token
userProfileManager.getUserInfo(accessToken: accessToken, identityToken: optionalIdentityToken) { (err, res) in
}
// Retrieve the UserInfo without any validation
userProfileManager.getUserInfo(accessToken: accessToken) { (err, res) in
}
此软件包包含根据 Apache License, Version 2.0(“许可证”)授权的代码。 您可以在 https://apache.ac.cn/licenses/LICENSE-2.0 获取许可证的副本,也可以查看此软件包中的 LICENSE 文件中的许可证。