• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

openid/AppAuth-iOS: iOS and macOS SDK for communicating with OAuth 2.0 and OpenI ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

openid/AppAuth-iOS

开源软件地址:

https://github.com/openid/AppAuth-iOS

开源编程语言:

Objective-C 98.8%

开源软件介绍:

AppAuth for iOS and macOS tests codecov Carthage compatible SwiftPM compatible Pod Version Pod License Pod Platform Catalyst compatible

AppAuth for iOS and macOS, and tvOS is a client SDK for communicating with OAuth 2.0 and OpenID Connect providers. It strives to directly map the requests and responses of those specifications, while following the idiomatic style of the implementation language. In addition to mapping the raw protocol flows, convenience methods are available to assist with common tasks like performing an action with fresh tokens.

It follows the best practices set out in RFC 8252 - OAuth 2.0 for Native Apps including using SFAuthenticationSession and SFSafariViewController on iOS for the auth request. UIWebView and WKWebView are explicitly not supported due to the security and usability reasons explained in Section 8.12 of RFC 8252.

It also supports the PKCE extension to OAuth, which was created to secure authorization codes in public clients when custom URI scheme redirects are used. The library is friendly to other extensions (standard or otherwise), with the ability to handle additional params in all protocol requests and responses.

For tvOS, AppAuth implements OAuth 2.0 Device Authorization Grant to allow for tvOS sign-ins through a secondary device.

Specification

iOS

Supported Versions

AppAuth supports iOS 7 and above.

iOS 9+ uses the in-app browser tab pattern (via SFSafariViewController), and falls back to the system browser (mobile Safari) on earlier versions.

Authorization Server Requirements

Both Custom URI Schemes (all supported versions of iOS) and Universal Links (iOS 9+) can be used with the library.

In general, AppAuth can work with any authorization server that supports native apps, as documented in RFC 8252, either through custom URI scheme redirects, or universal links. Authorization servers that assume all clients are web-based, or require clients to maintain confidentiality of the client secrets may not work well.

macOS

Supported Versions

AppAuth supports macOS (OS X) 10.9 and above.

Authorization Server Requirements

AppAuth for macOS supports both custom schemes; a loopback HTTP redirects via a small embedded server.

In general, AppAuth can work with any authorization server that supports native apps, as documented in RFC 8252; either through custom URI schemes, or loopback HTTP redirects. Authorization servers that assume all clients are web-based, or require clients to maintain confidentiality of the client secrets may not work well.

tvOS

Supported Versions

AppAuth supports tvOS 9.0 and above. Please note that while it is possible to run the standard AppAuth library on tvOS, the documentation below describes implementing OAuth 2.0 Device Authorization Grant (AppAuthTV).

Authorization Server Requirements

AppAuthTV is designed for servers that support the device authorization flow as documented in RFC 8628.

Try

Want to try out AppAuth? Just run:

pod try AppAuth

Follow the instructions in Examples/README.md to configure with your own OAuth client (you need to update three configuration points with your client info to try the demo).

Setup

AppAuth supports four options for dependency management.

CocoaPods

With CocoaPods, add the following line to your Podfile:

pod 'AppAuth'

Then, run pod install.

tvOS: Use the TV subspec:

pod 'AppAuth/TV'

Swift Package Manager

With Swift Package Manager, add the following dependency to your Package.swift:

dependencies: [
    .package(url: "https://github.com/openid/AppAuth-iOS.git", .upToNextMajor(from: "1.3.0"))
]

tvOS: Use the AppAuthTV target.

Carthage

With Carthage, add the following line to your Cartfile:

github "openid/AppAuth-iOS" "master"

Then, run carthage bootstrap.

tvOS: Use the AppAuthTV framework.

Static Library

You can also use AppAuth as a static library. This requires linking the library and your project, and including the headers. Here is a suggested configuration:

  1. Create an Xcode Workspace.
  2. Add AppAuth.xcodeproj to your Workspace.
  3. Include libAppAuth as a linked library for your target (in the "General -> Linked Framework and Libraries" section of your target).
  4. Add AppAuth-iOS/Source to your search paths of your target ("Build Settings -> "Header Search Paths").

Note: There is no static library for AppAuthTV.

Auth Flow

AppAuth supports both manual interaction with the authorization server where you need to perform your own token exchanges, as well as convenience methods that perform some of this logic for you. This example uses the convenience method, which returns either an OIDAuthState object, or an error.

OIDAuthState is a class that keeps track of the authorization and token requests and responses, and provides a convenience method to call an API with fresh tokens. This is the only object that you need to serialize to retain the authorization state of the session.

Configuration

You can configure AppAuth by specifying the endpoints directly:

Objective-C

NSURL *authorizationEndpoint =
    [NSURL URLWithString:@"https://accounts.google.com/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...

Swift

let authorizationEndpoint = URL(string: "https://accounts.google.com/o/oauth2/v2/auth")!
let tokenEndpoint = URL(string: "https://www.googleapis.com/oauth2/v4/token")!
let configuration = OIDServiceConfiguration(authorizationEndpoint: authorizationEndpoint,
                                            tokenEndpoint: tokenEndpoint)

// perform the auth request...

tvOS

Objective-C

NSURL *deviceAuthorizationEndpoint =
    [NSURL URLWithString:@"https://oauth2.googleapis.com/device/code"];
NSURL *tokenEndpoint =
    [NSURL URLWithString:@"https://www.googleapis.com/oauth2/v4/token"];

OIDTVServiceConfiguration *configuration =
    [[OIDTVServiceConfiguration alloc]
        initWithDeviceAuthorizationEndpoint:deviceAuthorizationEndpoint
                              tokenEndpoint:tokenEndpoint];

// perform the auth request...

Or through discovery:

Objective-C

NSURL *issuer = [NSURL URLWithString:@"https://accounts.google.com"];

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

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

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

Swift

let issuer = URL(string: "https://accounts.google.com")!

// discovers endpoints
OIDAuthorizationService.discoverConfiguration(forIssuer: issuer) { configuration, error in
  guard let config = configuration else {
    print("Error retrieving discovery document: \(error?.localizedDescription ?? "Unknown error")")
    return
  }

  // perform the auth request...
}

tvOS

Objective-C

NSURL *issuer = [NSURL URLWithString:@"https://accounts.google.com"];

[OIDTVAuthorizationService discoverServiceConfigurationForIssuer:issuer
    completion:^(OIDTVServiceConfiguration *_Nullable configuration,
                 NSError *_Nullable error) {

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

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

Authorizing – iOS

First, you need to have a property in your UIApplicationDelegate implementation to hold the session, in order to continue the authorization flow from the redirect. In this example, the implementation of this delegate is a class named AppDelegate, if your app's application delegate has a different name, please update the class name in samples below accordingly.

Objective-C

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

Swift

class AppDelegate: UIResponder, UIApplicationDelegate {
  // property of the app's AppDelegate
  var currentAuthorizationFlow: OIDExternalUserAgentSession?
}

And your main class, a property to store the auth state:

Objective-C

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

Swift

// property of the containing class
private var authState: OIDAuthState?

Then, initiate the authorization request. By using the authStateByPresentingAuthorizationRequest convenience method, the token exchange will be performed automatically, and everything will be protected with PKCE (if the server supports it). AppAuth also lets you perform these requests manually. See the authNoCodeExchange method in the included Example app for a demonstration:

Objective-C

// 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];
  }
}];

Swift

// builds authentication request
let request = OIDAuthorizationRequest(configuration: configuration,
                                      clientId: clientID,
                                      clientSecret: clientSecret,
                                      scopes: [OIDScopeOpenID, OIDScopeProfile],
                                      redirectURL: redirectURI,
                                      responseType: OIDResponseTypeCode,
                                      additionalParameters: nil)

// performs authentication request
print("Initiating authorization request with scope: \(request.scope ?? "nil")")

let appDelegate = UIApplication.shared.delegate as! AppDelegate

appDelegate.currentAuthorizationFlow =
    OIDAuthState.authState(byPresenting: request, presenting: self) { authState, error in
  if let authState = authState {
    self.setAuthState(authState)
    print("Got authorization tokens. Access token: " +
          "\(authState.lastTokenResponse?.accessToken ?? "nil")")
  } else {
    print("Authorization error: \(error?.localizedDescription ?? "Unknown error")")
    self.setAuthState(nil)
  }
}

Handling the Redirect

The authorization response URL is returned to the app via the iOS openURL app delegate method, so you need to pipe this through to the current authorization session (created in the previous session):

Objective-C

- (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;
}

Swift

func application(_ app: UIApplication,
                 open url: URL,
                 options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  // Sends the URL to the current authorization flow (if any) which will
  // process it if it relates to an authorization response.
  if let authorizationFlow = self.currentAuthorizationFlow,
                             authorizationFlow.resumeExternalUserAgentFlow(with: url) {
    self.currentAuthorizationFlow = nil
    return true
  }

  // Your additional URL handling (if any)

  return false
}

Authorizing – MacOS

On macOS, the most popular way to get the authorization response redirect is to start a local HTTP server on the loopback interface (limited to incoming requests from the user's machine only). When the authorization is complete, the user is redirected to that local server, and the authorization response can be processed by the app. AppAuth takes care of managing the local HTTP server lifecycle for you.


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap