OktaAppAuth 1.1.0.beta-okta

OktaAppAuth 1.1.0.beta-okta

Okta维护。



OktaAppAuth 1.1.0.beta-okta

  • 作者:
  • William Denniss 和 Steven E Wright

AppAuth for iOS and macOS Build Status Carthage compatible

iOS和macOS的AppAuth是为了与OAuth 2.0OpenID Connect提供者通信的客户端SDK。它力争直接映射那些规范中的请求数据和响应,同时遵循实现语言的约定式风格。除了映射原始协议流程外,还提供方便的方法,帮助执行使用新令牌的操作等常见任务。

它遵循RFC 8252 - 原生应用程序的OAuth 2.0中提出的最优实践,包括在iOS上使用SFAuthenticationSessionSFSafariViewController进行身份验证请求。UIWebViewWKWebView由于安全性和可用性原因(原因请参阅RFC 8252的第8.12节)明确不支持。

它还支持OAuth的PKCE扩展,该扩展旨在在公共客户端中使用自定义URI方案重定向时保护授权代码。此库能够友好地处理所有协议请求和响应中的额外参数,能够处理其他扩展(标准或有其他用途)。

规范

iOS

支持的版本

AppAuth支持iOS 7及以上。

iOS 9+使用应用程序浏览器标签模式(通过SFSafariViewController),在早期版本上回退至系统浏览器(移动Safari)。

认证服务器要求

库可以与自定义URI方案(所有受支持的iOS版本)和通用链接(iOS 9以上版本)一起使用。

一般情况下,AppAuth可以与任何支持原生应用的认证服务器(AS),如RFC 8252中所述,通过自定义URI方案重定向或通用链接进行工作。假设所有客户端都是基于Web或要求客户端维护客户端机密性保密的服务器可能工作不佳。

macOS

支持的版本

AppAuth支持macOS(OS X)10.9及以上版本。

认证服务器要求

AppAuth for macOS同时支持自定义方案和通过小型嵌入式服务器实现的回环HTTP重定向。

一般情况下,AppAuth可以与任何支持原生应用的认证服务器(AS),如RFC 8252中所述,通过自定义URI方案或回环HTTP重定向进行工作。假设所有客户端都是基于Web或要求客户端维护客户端机密性保密的服务器可能工作不佳。

尝试

想要试用AppAuth吗?只需运行

pod try AppAuth

按照Examples/README.md中的说明进行操作以配置您的OAuth客户端(您需要更改3个配置点以包含客户端信息以尝试演示)。

设置

AppAuth支持三种依赖管理选项。

CocoaPods

使用CocoaPods,将以下行添加到您的Podfile

pod 'AppAuth'

然后运行pod install

Carthage

使用Carthage,将以下行添加到您的Cartfile

github "openid/AppAuth-iOS" "master"

然后运行carthage bootstrap

静态库

您还可以将AppAuth用作静态库。这需要链接库和您的项目,并包括头文件。建议配置

  1. 创建一个Xcode Workspace。
  2. AppAuth.xcodeproj添加到您的Workspace中。
  3. 将libAppAuth视为您的目标链接库(在您的目标“通用 -> 链接框架和库”部分中)。
  4. AppAuth-iOS/Source添加到您的目标搜索路径中(在“构建设置 -> ”头文件搜索路径”中)。

认证流程

AppAuth同时支持与授权服务器手动交互以执行自己的令牌交换,以及执行某些逻辑的便利方法。此示例使用便利方法,它返回一个OIDAuthState对象或一个错误。

OIDAuthState是一个跟踪授权和令牌请求以及响应的类,并为调用带有新鲜令牌的API提供了便利方法。这是唯一需要序列化以保留会话授权状态的对象。

配置

您可以通过指定端点直接配置AppAuth。

NSURL *authorizationEndpoint =
    [NSURL URLWithString:@"https://#/o/oauth2/v2/auth"];
NSURL *tokenEndpoint =
    [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v4/token"];

OIDServiceConfiguration *configuration =
    [[OIDServiceConfiguration alloc]
        initWithAuthorizationEndpoint:authorizationEndpoint
                        tokenEndpoint:tokenEndpoint];

// perform the auth request...

或者通过发现机制。

NSURL *issuer = [NSURL URLWithString:@"https://#"];

[OIDAuthorizationService discoverServiceConfigurationForIssuer:issuer
    completion:^(OIDServiceConfiguration *_Nullable configuration,
                 NSError *_Nullable error) {

  if (!configuration) {
    NSLog(@"Error retrieving discovery document: %@",
          [error localizedDescription]);
    return;
  }

  // perform the auth request...
}];

授权 – iOS

首先,您需要在AppDelegate中添加一个属性来存储会话,以便从重定向继续授权流程。

// property of the app's AppDelegate
@property(nonatomic, strong, nullable)
    id<OIDExternalUserAgentSession> currentAuthorizationFlow;

然后在您的主类中,一个属性用于存储授权状态

// property of the containing class
@property(nonatomic, strong, nullable) OIDAuthState *authState;

然后,发起授权请求。通过使用authStateByPresentingAuthorizationRequest便捷方法,将自动执行令牌交换,一切都会通过PKCE(如果服务器支持)得到保护。AppAuth还允许您手动执行这些请求。请参考包含示例应用程序中的authNoCodeExchange方法进行演示。

// builds authentication request
OIDAuthorizationRequest *request =
    [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
                                                  clientId:kClientID
                                                    scopes:@[OIDScopeOpenID,
                                                             OIDScopeProfile]
                                               redirectURL:KRedirectURI
                                              responseType:OIDResponseTypeCode
                                      additionalParameters:nil];

// performs authentication request
AppDelegate *appDelegate =
    (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.currentAuthorizationFlow =
    [OIDAuthState authStateByPresentingAuthorizationRequest:request
        presentingViewController:self
                        callback:^(OIDAuthState *_Nullable authState,
                                   NSError *_Nullable error) {
  if (authState) {
    NSLog(@"Got authorization tokens. Access token: %@",
          authState.lastTokenResponse.accessToken);
    [self setAuthState:authState];
  } else {
    NSLog(@"Authorization error: %@", [error localizedDescription]);
    [self setAuthState:nil];
  }
}];

处理重定向

授权响应URL将通过iOS的openURL应用程序代理方法返回给应用程序,因此您需要将其传递到当前授权会话(在之前会话中创建)。

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<NSString *, id> *)options {
  // Sends the URL to the current authorization flow (if any) which will
  // process it if it relates to an authorization response.
  if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
    _currentAuthorizationFlow = nil;
    return YES;
  }

  // Your additional URL handling (if any) goes here.

  return NO;
}

授权 – MacOS

在macOS上,获取授权响应重定向最流行的方式是在环回接口上启动本地HTTP服务器(仅限于用户机器的入站请求)。授权完成后,用户将被重定向到该本地服务器,应用程序可以处理授权响应。AppAuth会为您管理本地HTTP服务器的生命周期。

💡备选方案:自定义URI方案

macOS也支持自定义URI方案,但某些浏览器会显示一个中继界面,从而降低了可用性。有关使用自定义URI方案与macOS的示例,请参见Example-Mac

要使用本地HTTP服务器接收授权响应,首先您需要在您的主类中添加一个实例变量以保留HTTP重定向处理程序。

OIDRedirectHTTPHandler *_redirectHTTPHandler;

然后,由于本地HTTP服务器使用的端口可能不同,您需要在构建授权请求之前启动它,以便获取要使用的确切重定向URI。

static NSString *const kSuccessURLString =
    @"http://openid.github.io/AppAuth-iOS/redirect/";
NSURL *successURL = [NSURL URLWithString:kSuccessURLString];

// Starts a loopback HTTP redirect listener to receive the code.  This needs to be started first,
// as the exact redirect URI (including port) must be passed in the authorization request.
_redirectHTTPHandler = [[OIDRedirectHTTPHandler alloc] initWithSuccessURL:successURL];
NSURL *redirectURI = [_redirectHTTPHandler startHTTPListener:nil];

然后,发起授权请求。通过使用authStateByPresentingAuthorizationRequest便捷方法,将自动执行令牌交换,一切都会通过PKCE(如果服务器支持)得到保护。通过将返回值分配给OIDRedirectHTTPHandlercurrentAuthorizationFlow,一旦用户做出选择,授权将自动继续。

// builds authentication request
OIDAuthorizationRequest *request =
    [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
                                                  clientId:kClientID
                                              clientSecret:kClientSecret
                                                    scopes:@[ OIDScopeOpenID ]
                                               redirectURL:redirectURI
                                              responseType:OIDResponseTypeCode
                                      additionalParameters:nil];
// performs authentication request
__weak __typeof(self) weakSelf = self;
_redirectHTTPHandler.currentAuthorizationFlow =
    [OIDAuthState authStateByPresentingAuthorizationRequest:request
                        callback:^(OIDAuthState *_Nullable authState,
                                   NSError *_Nullable error) {
  // Brings this app to the foreground.
  [[NSRunningApplication currentApplication]
      activateWithOptions:(NSApplicationActivateAllWindows |
                           NSApplicationActivateIgnoringOtherApps)];

  // Processes the authorization response.
  if (authState) {
    NSLog(@"Got authorization tokens. Access token: %@",
          authState.lastTokenResponse.accessToken);
  } else {
    NSLog(@"Authorization error: %@", error.localizedDescription);
  }
  [weakSelf setAuthState:authState];
}];

编写API调用

AppAuth为您提供了原始令牌信息。然而,我们建议使用OIDAuthState便利封装器的用户使用提供的performActionWithFreshTokens:方法来执行API调用,以避免担心令牌的时效性。

[_authState performActionWithFreshTokens:^(NSString *_Nonnull accessToken,
                                           NSString *_Nonnull idToken,
                                           NSError *_Nullable error) {
  if (error) {
    NSLog(@"Error fetching fresh tokens: %@", [error localizedDescription]);
    return;
  }

  // perform your API request using the tokens
}];

API文档

浏览API文档

包含的示例

您可以通过打开源分布中的iOS示例来尝试iOS示例,进入Example/Example.xcworkspace。您可以通过删除AppAuth项目并配置pod来轻松地将示例工作区转换为Pod工作区。您还可以通过CocoaPods尝试示例。请务必遵循Example/README.md中的说明来配置自己的OAuth客户端ID以在示例中使用。

您可以通过在Example-Mac文件夹中执行pod install来尝试源分布中包含的macOS示例,然后打开Example-Mac.xcworkspace。请务必遵循Example-Mac/README.md中的说明来配置自己的OAuth客户端ID以在示例中使用。