Skip to content

Commit

Permalink
Making the FlowSessions and UICoordinators generic, so they can be us…
Browse files Browse the repository at this point in the history
…ed for more than just authorization purposes. Relates to issue #195
  • Loading branch information
Lucas Farris committed Feb 12, 2018
1 parent 135f99d commit c8c6864
Show file tree
Hide file tree
Showing 31 changed files with 457 additions and 296 deletions.
110 changes: 70 additions & 40 deletions AppAuth.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions Source/AppAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
*/

#import "OIDAuthState.h"
#import "OIDAuthorizationFlowSession.h"
#import "OIDAuthStateChangeDelegate.h"
#import "OIDAuthStateErrorDelegate.h"
#import "OIDAuthorizationRequest.h"
#import "OIDAuthorizationResponse.h"
#import "OIDAuthorizationService.h"
#import "OIDAuthorizationUICoordinator.h"
#import "OIDError.h"
#import "OIDErrorUtilities.h"
#import "OIDExternalUserAgentFlowSession.h"
#import "OIDExternalUserAgentUICoordinator.h"
#import "OIDGrantTypes.h"
#import "OIDRegistrationRequest.h"
#import "OIDRegistrationResponse.h"
Expand All @@ -43,12 +45,11 @@
#elif TARGET_OS_IOS
#import "OIDAuthState+IOS.h"
#import "OIDAuthorizationService+IOS.h"
#import "OIDAuthorizationUICoordinatorCustomBrowser.h"
#import "OIDAuthorizationUICoordinatorIOS.h"
#import "OIDExternalUserAgentUICoordinatorCustomBrowser.h"
#elif TARGET_OS_MAC
#import "OIDAuthState+Mac.h"
#import "OIDAuthorizationService+Mac.h"
#import "OIDAuthorizationUICoordinatorMac.h"
#import "OIDExternalUserAgentUICoordinatorMac.h"
#import "OIDRedirectHTTPHandler.h"
#else
#error "Platform Undefined"
Expand Down
8 changes: 4 additions & 4 deletions Source/Framework/AppAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ FOUNDATION_EXPORT const unsigned char AppAuthVersionString[];
#import <AppAuth/OIDAuthorizationRequest.h>
#import <AppAuth/OIDAuthorizationResponse.h>
#import <AppAuth/OIDAuthorizationService.h>
#import <AppAuth/OIDAuthorizationUICoordinator.h>
#import <AppAuth/OIDExternalUserAgentUICoordinator.h>
#import <AppAuth/OIDError.h>
#import <AppAuth/OIDErrorUtilities.h>
#import <AppAuth/OIDGrantTypes.h>
Expand All @@ -50,12 +50,12 @@ FOUNDATION_EXPORT const unsigned char AppAuthVersionString[];
#elif TARGET_OS_IOS
#import <AppAuth/OIDAuthState+IOS.h>
#import <AppAuth/OIDAuthorizationService+IOS.h>
#import <AppAuth/OIDAuthorizationUICoordinatorCustomBrowser.h>
#import <AppAuth/OIDAuthorizationUICoordinatorIOS.h>
#import <AppAuth/OIDExternalUserAgentUICoordinatorCustomBrowser.h>
#import <AppAuth/OIDExternalUserAgentUICoordinatorIOS.h>
#elif TARGET_OS_MAC
#import <AppAuth/OIDAuthState+Mac.h>
#import <AppAuth/OIDAuthorizationService+Mac.h>
#import <AppAuth/OIDAuthorizationUICoordinatorMac.h>
#import <AppAuth/OIDExternalUserAgentUICoordinatorMac.h>
#import <AppAuth/OIDRedirectHTTPHandler.h>
#else
#error "Platform Undefined"
Expand Down
16 changes: 8 additions & 8 deletions Source/OIDAuthState.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
@class OIDTokenResponse;
@class OIDTokenRequest;
@protocol OIDAuthorizationFlowSession;
@protocol OIDAuthorizationUICoordinator;
@protocol OIDAuthStateChangeDelegate;
@protocol OIDAuthStateErrorDelegate;
@protocol OIDExternalUserAgentUICoordinator;
@protocol OIDExternalUserAgentFlowSession;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -142,16 +143,15 @@ typedef void (^OIDAuthStateAuthorizationCallback)(OIDAuthState *_Nullable authSt
/*! @brief Convenience method to create a @c OIDAuthState by presenting an authorization request
and performing the authorization code exchange in the case of code flow requests.
@param authorizationRequest The authorization request to present.
@param UICoordinator Generic authorization UI coordinator that can present an authorization
request.
@param UICoordinator Generic UI coordinator that can present an external user-agent request.
@param callback The method called when the request has completed or failed.
@return A @c OIDAuthorizationFlowSession instance which will terminate when it
receives a @c OIDAuthorizationFlowSession.cancel message, or after processing a
@c OIDAuthorizationFlowSession.resumeAuthorizationFlowWithURL: message.
@return A @c OIDExternalUserAgentFlowSession instance which will terminate when it
receives a @c OIDExternalUserAgentFlowSession.cancel message, or after processing a
@c OIDExternalUserAgentFlowSession.resumeExternalUserAgentFlowWithURL: message.
*/
+ (id<OIDAuthorizationFlowSession>)
+ (id<OIDExternalUserAgentFlowSession, OIDAuthorizationFlowSession>)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
UICoordinator:(id<OIDAuthorizationUICoordinator>)UICoordinator
UICoordinator:(id<OIDExternalUserAgentUICoordinator>)UICoordinator
callback:(OIDAuthStateAuthorizationCallback)callback;

/*! @internal
Expand Down
10 changes: 5 additions & 5 deletions Source/OIDAuthState.m
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ @implementation OIDAuthState

#pragma mark - Convenience initializers

+ (id<OIDAuthorizationFlowSession>)
+ (id<OIDExternalUserAgentFlowSession, OIDAuthorizationFlowSession>)
authStateByPresentingAuthorizationRequest:(OIDAuthorizationRequest *)authorizationRequest
UICoordinator:(id<OIDAuthorizationUICoordinator>)UICoordinator
UICoordinator:(id<OIDExternalUserAgentUICoordinator>)UICoordinator
callback:(OIDAuthStateAuthorizationCallback)callback {
// presents the authorization request
id<OIDAuthorizationFlowSession> authFlowSession = [OIDAuthorizationService
id<OIDExternalUserAgentFlowSession, OIDAuthorizationFlowSession> authFlowSession = [OIDAuthorizationService
presentAuthorizationRequest:authorizationRequest
UICoordinator:UICoordinator
callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse,
Expand Down Expand Up @@ -157,15 +157,15 @@ - (nonnull instancetype)init
OID_UNAVAILABLE_USE_INITIALIZER(@selector(initWithAuthorizationResponse:tokenResponse:));

/*! @brief Creates an auth state from an authorization response.
@param response The authorization response.
@param authorizationResponse The authorization response.
*/
- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse {
return [self initWithAuthorizationResponse:authorizationResponse tokenResponse:nil];
}


/*! @brief Designated initializer.
@param response The authorization response.
@param authorizationResponse The authorization response.
@discussion Creates an auth state from an authorization response and token response.
*/
- (instancetype)initWithAuthorizationResponse:(OIDAuthorizationResponse *)authorizationResponse
Expand Down
42 changes: 42 additions & 0 deletions Source/OIDAuthorizationFlowSession.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*! @file OIDAuthorizationRequest.h
@brief AppAuth iOS SDK
@copyright
Copyright 2015 Google Inc. All Rights Reserved.
@copydetails
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*! @brief Represents an in-flight authorization flow session.
*/
@protocol OIDAuthorizationFlowSession <NSObject>

/*! @brief Clients should call this method with the result of the authorization code flow if it
becomes available.
@param URL The redirect URL invoked by the authorization server.
@discussion When the URL represented a valid authorization response, implementations
should clean up any left-over UI state from the authorization, for example by
closing the \SFSafariViewController or looback HTTP listener if those were used.
The completion block of the pending authorization request should then be invoked.
@remarks Has no effect if called more than once, or after a @c cancel message was received.
@return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise.
*/
- (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL;

/*! @brief @c OIDAuthorizationUICoordinator or clients should call this method when the
authorization flow failed with a non-OAuth error.
@param error The error that is the reason for the failure of this authorization flow.
@remarks Has no effect if called more than once, or after a @c cancel message was received.
*/
- (void)failAuthorizationFlowWithError:(NSError *)error;

@end
3 changes: 2 additions & 1 deletion Source/OIDAuthorizationRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// These files only declare string constants useful for constructing a @c OIDAuthorizationRequest,
// so they are imported here for convenience.
#import "OIDExternalUserAgentRequest.h"
#import "OIDResponseTypes.h"
#import "OIDScopes.h"

Expand All @@ -37,7 +38,7 @@ extern NSString *const OIDOAuthorizationRequestCodeChallengeMethodS256;
@see https://tools.ietf.org/html/rfc6749#section-4
@see https://tools.ietf.org/html/rfc6749#section-4.1.1
*/
@interface OIDAuthorizationRequest : NSObject <NSCopying, NSSecureCoding> {
@interface OIDAuthorizationRequest : NSObject <NSCopying, NSSecureCoding, OIDExternalUserAgentRequest> {
// property variables
OIDServiceConfiguration *_configuration;
NSString *_responseType;
Expand Down
10 changes: 10 additions & 0 deletions Source/OIDAuthorizationRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,14 @@ - (NSURL *)authorizationRequestURL {
return [query URLByReplacingQueryInURL:_configuration.authorizationEndpoint];
}

#pragma mark - OIDExternalUserAgentRequest

- (NSURL *)externalUserAgentRequestURL {
return [self authorizationRequestURL];
}

- (NSString *)redirectScheme {
return [[self redirectURL] scheme];
}

@end
47 changes: 7 additions & 40 deletions Source/OIDAuthorizationService.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
@class OIDTokenRequest;
@class OIDTokenResponse;
@protocol OIDAuthorizationFlowSession;
@protocol OIDAuthorizationUICoordinator;
@protocol OIDExternalUserAgentFlowSession;
@protocol OIDExternalUserAgentUICoordinator;

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -115,13 +116,13 @@ typedef void (^OIDRegistrationCompletion)(OIDRegistrationResponse *_Nullable reg
@param UICoordinator Generic authorization UI coordinator that can present an authorization
request.
@param callback The method called when the request has completed or failed.
@return A @c OIDAuthorizationFlowSession instance which will terminate when it
receives a @c OIDAuthorizationFlowSession.cancel message, or after processing a
@c OIDAuthorizationFlowSession.resumeAuthorizationFlowWithURL: message.
@return A @c OIDExternalUserAgentFlowSession instance which will terminate when it
receives a @c OIDExternalUserAgentFlowSession.cancel message, or after processing a
@c OIDExternalUserAgentFlowSession.resumeExternalUserAgentFlowWithURL: message.
*/
+ (id<OIDAuthorizationFlowSession>)
+ (id<OIDExternalUserAgentFlowSession, OIDAuthorizationFlowSession>)
presentAuthorizationRequest:(OIDAuthorizationRequest *)request
UICoordinator:(id<OIDAuthorizationUICoordinator>)UICoordinator
UICoordinator:(id<OIDExternalUserAgentUICoordinator>)UICoordinator
callback:(OIDAuthorizationCallback)callback;

/*! @brief Performs a token request.
Expand All @@ -139,38 +140,4 @@ typedef void (^OIDRegistrationCompletion)(OIDRegistrationResponse *_Nullable reg

@end

/*! @brief Represents an in-flight authorization flow session.
*/
@protocol OIDAuthorizationFlowSession <NSObject>

/*! @brief Cancels the code flow session, invoking the request's callback with a cancelled error.
@remarks Has no effect if called more than once, or after a
@c OIDAuthorizationFlowSession.resumeAuthorizationFlowWithURL: message was received. Will
cause an error with code: @c ::OIDErrorCodeProgramCanceledAuthorizationFlow to be passed to
the @c callback block passed to
@c OIDAuthorizationService.presentAuthorizationRequest:presentingViewController:callback:
*/
- (void)cancel;

/*! @brief Clients should call this method with the result of the authorization code flow if it
becomes available.
@param URL The redirect URL invoked by the authorization server.
@discussion When the URL represented a valid authorization response, implementations
should clean up any left-over UI state from the authorization, for example by
closing the \SFSafariViewController or looback HTTP listener if those were used.
The completion block of the pending authorization request should then be invoked.
@remarks Has no effect if called more than once, or after a @c cancel message was received.
@return YES if the passed URL matches the expected redirect URL and was consumed, NO otherwise.
*/
- (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL;

/*! @brief @c OIDAuthorizationUICoordinator or clients should call this method when the
authorization flow failed with a non-OAuth error.
@param error The error that is the reason for the failure of this authorization flow.
@remarks Has no effect if called more than once, or after a @c cancel message was received.
*/
- (void)failAuthorizationFlowWithError:(NSError *)error;

@end

NS_ASSUME_NONNULL_END
50 changes: 29 additions & 21 deletions Source/OIDAuthorizationService.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@

#import "OIDAuthorizationRequest.h"
#import "OIDAuthorizationResponse.h"
#import "OIDAuthorizationUICoordinator.h"
#import "OIDDefines.h"
#import "OIDErrorUtilities.h"
#import "OIDAuthorizationFlowSession.h"
#import "OIDExternalUserAgentFlowSession.h"
#import "OIDExternalUserAgentUICoordinator.h"
#import "OIDRegistrationRequest.h"
#import "OIDRegistrationResponse.h"
#import "OIDServiceConfiguration.h"
Expand All @@ -40,10 +42,10 @@

NS_ASSUME_NONNULL_BEGIN

@interface OIDAuthorizationFlowSessionImplementation : NSObject<OIDAuthorizationFlowSession> {
@interface OIDAuthorizationFlowSessionImplementation : NSObject<OIDExternalUserAgentFlowSession, OIDAuthorizationFlowSession> {
// private variables
OIDAuthorizationRequest *_request;
id<OIDAuthorizationUICoordinator> _UICoordinator;
id<OIDExternalUserAgentUICoordinator> _UICoordinator;
OIDAuthorizationCallback _pendingauthorizationFlowCallback;
}

Expand All @@ -64,12 +66,12 @@ - (instancetype)initWithRequest:(OIDAuthorizationRequest *)request {
return self;
}

- (void)presentAuthorizationWithCoordinator:(id<OIDAuthorizationUICoordinator>)UICoordinator
- (void)presentAuthorizationWithCoordinator:(id<OIDExternalUserAgentUICoordinator>)UICoordinator
callback:(OIDAuthorizationCallback)authorizationFlowCallback {
_UICoordinator = UICoordinator;
_pendingauthorizationFlowCallback = authorizationFlowCallback;
BOOL authorizationFlowStarted =
[_UICoordinator presentAuthorizationRequest:_request session:self];
[_UICoordinator presentExternalUserAgentRequest:_request session:self];
if (!authorizationFlowStarted) {
NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
underlyingError:nil
Expand All @@ -79,14 +81,13 @@ - (void)presentAuthorizationWithCoordinator:(id<OIDAuthorizationUICoordinator>)U
}

- (void)cancel {
[_UICoordinator dismissAuthorizationAnimated:YES
completion:^{
NSError *error = [OIDErrorUtilities
errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
underlyingError:nil
description:nil];
[self didFinishWithResponse:nil error:error];
}];
[_UICoordinator dismissExternalUserAgentUIAnimated:YES completion:^{
NSError *error = [OIDErrorUtilities
errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
underlyingError:nil
description:nil];
[self didFinishWithResponse:nil error:error];
}];
}

- (BOOL)shouldHandleURL:(NSURL *)URL {
Expand All @@ -101,7 +102,7 @@ - (BOOL)shouldHandleURL:(NSURL *)URL {
OIDIsEqualIncludingNil(standardizedURL.path, standardizedRedirectURL.path);
}

- (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL {
- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL {
// rejects URLs that don't match redirect (these may be completely unrelated to the authorization)
if (![self shouldHandleURL:URL]) {
return NO;
Expand Down Expand Up @@ -145,15 +146,14 @@ - (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL {
}
}

[_UICoordinator dismissAuthorizationAnimated:YES
completion:^{
[self didFinishWithResponse:response error:error];
}];
[_UICoordinator dismissExternalUserAgentUIAnimated:YES completion:^{
[self didFinishWithResponse:response error:error];
}];

return YES;
}

- (void)failAuthorizationFlowWithError:(NSError *)error {
- (void)failExternalUserAgentFlowWithError:(NSError *)error {
[self didFinishWithResponse:nil error:error];
}

Expand All @@ -171,6 +171,14 @@ - (void)didFinishWithResponse:(nullable OIDAuthorizationResponse *)response
}
}

- (void)failAuthorizationFlowWithError:(NSError *)error {
[self failAuthorizationFlowWithError:error];
}

- (BOOL)resumeAuthorizationFlowWithURL:(NSURL *)URL {
return [self resumeExternalUserAgentFlowWithURL:URL];
}

@end

@implementation OIDAuthorizationService
Expand Down Expand Up @@ -245,9 +253,9 @@ + (void)discoverServiceConfigurationForDiscoveryURL:(NSURL *)discoveryURL

#pragma mark - Authorization Endpoint

+ (id<OIDAuthorizationFlowSession>)
+ (id<OIDExternalUserAgentFlowSession, OIDAuthorizationFlowSession>)
presentAuthorizationRequest:(OIDAuthorizationRequest *)request
UICoordinator:(id<OIDAuthorizationUICoordinator>)UICoordinator
UICoordinator:(id<OIDExternalUserAgentUICoordinator>)UICoordinator
callback:(OIDAuthorizationCallback)callback {
OIDAuthorizationFlowSessionImplementation *flowSession =
[[OIDAuthorizationFlowSessionImplementation alloc] initWithRequest:request];
Expand Down
Loading

0 comments on commit c8c6864

Please sign in to comment.