RNAppAuth.m (react-native-app-auth@7.1.3)
28 removals
413 lines
26 additions
411 lines
#import "RNAppAuth.h"
#import "RNAppAuth.h"
#if __has_include(<AppAuth/AppAuth.h>)
#if __has_include(<AppAuth/AppAuth.h>)
#import <AppAuth/AppAuth.h>
#import <AppAuth/AppAuth.h>
#else
#else
#import "AppAuth.h"
#import "AppAuth.h"
#endif
#endif
#import <React/RCTLog.h>
#import <React/RCTLog.h>
#import <React/RCTConvert.h>
#import <React/RCTConvert.h>
#import "RNAppAuthAuthorizationFlowManager.h"
#import "RNAppAuthAuthorizationFlowManager.h"
@interface RNAppAuth()<RNAppAuthAuthorizationFlowManagerDelegate> {
@interface RNAppAuth()<RNAppAuthAuthorizationFlowManagerDelegate> {
id<OIDExternalUserAgentSession> _currentSession;
id<OIDExternalUserAgentSession> _currentSession;
}
}
@property (nonatomic, copy) RCTPromiseRejectBlock authorizeRejectBlock;
@end
@end
@implementation RNAppAuth
@implementation RNAppAuth
-(BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url {
-(BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url {
return [_currentSession resumeExternalUserAgentFlowWithURL:url];
return [_currentSession resumeExternalUserAgentFlowWithURL:url];
}
}
- (dispatch_queue_t)methodQueue
- (dispatch_queue_t)methodQueue
{
{
return dispatch_get_main_queue();
return dispatch_get_main_queue();
}
}
UIBackgroundTaskIdentifier rnAppAuthTaskId;
UIBackgroundTaskIdentifier rnAppAuthTaskId;
/*! @brief Number of random bytes generated for the @ state.
/*! @brief Number of random bytes generated for the @ state.
*/
*/
static NSUInteger const kStateSizeBytes = 32;
static NSUInteger const kStateSizeBytes = 32;
/*! @brief Number of random bytes generated for the @ codeVerifier.
/*! @brief Number of random bytes generated for the @ codeVerifier.
*/
*/
static NSUInteger const kCodeVerifierBytes = 32;
static NSUInteger const kCodeVerifierBytes = 32;
RCT_EXPORT_MODULE()
RCT_EXPORT_MODULE()
RCT_REMAP_METHOD(cancelAuthorizationFlow,
cancelAuthorizationFlowWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
if (self->_currentSession) {
id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate;
UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController;
[presentingViewController dismissViewControllerAnimated:YES completion:^{
resolve(@"Authorization flow cancelled");
self->_currentSession = nil;
NSError *error = [NSError errorWithDomain:@"RNAppAuth" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Authorization flow cancelled"}];
if(self.authorizeRejectBlock != nil) {
self.authorizeRejectBlock([self getErrorCode: error defaultCode:@"browser_force_closed"], @"Authorization flow cancelled", error);
}
self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks.
}];
} else {
NSError *error = [NSError errorWithDomain:@"RNAppAuth" code:500 userInfo:@{NSLocalizedDescriptionKey: @"No current session available to cancel"}];
reject(@"no_current_session", @"No current session available to cancel", error);
}
}
RCT_REMAP_METHOD(register,
RCT_REMAP_METHOD(register,
issuer: (NSString *) issuer
issuer: (NSString *) issuer
redirectUrls: (NSArray *) redirectUrls
redirectUrls: (NSArray *) redirectUrls
responseTypes: (NSArray *) responseTypes
responseTypes: (NSArray *) responseTypes
grantTypes: (NSArray *) grantTypes
grantTypes: (NSArray *) grantTypes
subjectType: (NSString *) subjectType
subjectType: (NSString *) subjectType
tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod
tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod
additionalParameters: (NSDictionary *_Nullable) additionalParameters
additionalParameters: (NSDictionary *_Nullable) additionalParameters
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
connectionTimeoutSeconds: (double) connectionTimeoutSeconds
connectionTimeoutSeconds: (double) connectionTimeoutSeconds
additionalHeaders: (NSDictionary *_Nullable) additionalHeaders
additionalHeaders: (NSDictionary *_Nullable) additionalHeaders
resolve: (RCTPromiseResolveBlock) resolve
resolve: (RCTPromiseResolveBlock) resolve
reject: (RCTPromiseRejectBlock) reject)
reject: (RCTPromiseRejectBlock) reject)
{
{
[self configureUrlSession:additionalHeaders sessionTimeout:connectionTimeoutSeconds];
[self configureUrlSession:additionalHeaders sessionTimeout:connectionTimeoutSeconds];
// if we have manually provided configuration, we can use it and skip the OIDC well-known discovery endpoint call
// if we have manually provided configuration, we can use it and skip the OIDC well-known discovery endpoint call
if (serviceConfiguration) {
if (serviceConfiguration) {
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
[self registerWithConfiguration: configuration
[self registerWithConfiguration: configuration
redirectUrls: redirectUrls
redirectUrls: redirectUrls
responseTypes: responseTypes
responseTypes: responseTypes
grantTypes: grantTypes
grantTypes: grantTypes
subjectType: subjectType
subjectType: subjectType
tokenEndpointAuthMethod: tokenEndpointAuthMethod
tokenEndpointAuthMethod: tokenEndpointAuthMethod
additionalParameters: additionalParameters
additionalParameters: additionalParameters
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
} else {
} else {
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
if (!configuration) {
if (!configuration) {
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
return;
return;
}
}
[self registerWithConfiguration: configuration
[self registerWithConfiguration: configuration
redirectUrls: redirectUrls
redirectUrls: redirectUrls
responseTypes: responseTypes
responseTypes: responseTypes
grantTypes: grantTypes
grantTypes: grantTypes
subjectType: subjectType
subjectType: subjectType
tokenEndpointAuthMethod: tokenEndpointAuthMethod
tokenEndpointAuthMethod: tokenEndpointAuthMethod
additionalParameters: additionalParameters
additionalParameters: additionalParameters
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
}];
}];
}
}
} // end RCT_REMAP_METHOD(register,
} // end RCT_REMAP_METHOD(register,
RCT_REMAP_METHOD(authorize,
RCT_REMAP_METHOD(authorize,
issuer: (NSString *) issuer
issuer: (NSString *) issuer
redirectUrl: (NSString *) redirectUrl
redirectUrl: (NSString *) redirectUrl
clientId: (NSString *) clientId
clientId: (NSString *) clientId
clientSecret: (NSString *) clientSecret
clientSecret: (NSString *) clientSecret
scopes: (NSArray *) scopes
scopes: (NSArray *) scopes
additionalParameters: (NSDictionary *_Nullable) additionalParameters
additionalParameters: (NSDictionary *_Nullable) additionalParameters
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
skipCodeExchange: (BOOL) skipCodeExchange
skipCodeExchange: (BOOL) skipCodeExchange
connectionTimeoutSeconds: (double) connectionTimeoutSeconds
connectionTimeoutSeconds: (double) connectionTimeoutSeconds
additionalHeaders: (NSDictionary *_Nullable) additionalHeaders
additionalHeaders: (NSDictionary *_Nullable) additionalHeaders
useNonce: (BOOL *) useNonce
useNonce: (BOOL *) useNonce
usePKCE: (BOOL *) usePKCE
usePKCE: (BOOL *) usePKCE
iosCustomBrowser: (NSString *) iosCustomBrowser
iosCustomBrowser: (NSString *) iosCustomBrowser
prefersEphemeralSession: (BOOL *) prefersEphemeralSession
prefersEphemeralSession: (BOOL *) prefersEphemeralSession
resolve: (RCTPromiseResolveBlock) resolve
resolve: (RCTPromiseResolveBlock) resolve
reject: (RCTPromiseRejectBlock) reject)
reject: (RCTPromiseRejectBlock) reject)
{
{
self.authorizeRejectBlock = reject;
[self configureUrlSession:additionalHeaders sessionTimeout:connectionTimeoutSeconds];
[self configureUrlSession:additionalHeaders sessionTimeout:connectionTimeoutSeconds];
// if we have manually provided configuration, we can use it and skip the OIDC well-known discovery endpoint call
// if we have manually provided configuration, we can use it and skip the OIDC well-known discovery endpoint call
if (serviceConfiguration) {
if (serviceConfiguration) {
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
[self authorizeWithConfiguration: configuration
[self authorizeWithConfiguration: configuration
redirectUrl: redirectUrl
redirectUrl: redirectUrl
clientId: clientId
clientId: clientId
clientSecret: clientSecret
clientSecret: clientSecret
scopes: scopes
scopes: scopes
useNonce: useNonce
useNonce: useNonce
usePKCE: usePKCE
usePKCE: usePKCE
additionalParameters: additionalParameters
additionalParameters: additionalParameters
skipCodeExchange: skipCodeExchange
skipCodeExchange: skipCodeExchange
iosCustomBrowser: iosCustomBrowser
iosCustomBrowser: iosCustomBrowser
prefersEphemeralSession: prefersEphemeralSession
prefersEphemeralSession: prefersEphemeralSession
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
} else {
} else {
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
if (!configuration) {
if (!configuration) {
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks.
return;
return;
}
}
[self authorizeWithConfiguration: configuration
[self authorizeWithConfiguration: configuration
redirectUrl: redirectUrl
redirectUrl: redirectUrl
clientId: clientId
clientId: clientId
clientSecret: clientSecret
clientSecret: clientSecret
scopes: scopes
scopes: scopes
useNonce: useNonce
useNonce: useNonce
usePKCE: usePKCE
usePKCE: usePKCE
additionalParameters: additionalParameters
additionalParameters: additionalParameters
skipCodeExchange: skipCodeExchange
skipCodeExchange: skipCodeExchange
iosCustomBrowser: iosCustomBrowser
iosCustomBrowser: iosCustomBrowser
prefersEphemeralSession: prefersEphemeralSession
prefersEphemeralSession: prefersEphemeralSession
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
}];
}];
}
}
} // end RCT_REMAP_METHOD(authorize,
} // end RCT_REMAP_METHOD(authorize,
RCT_REMAP_METHOD(refresh,
RCT_REMAP_METHOD(refresh,
issuer: (NSString *) issuer
issuer: (NSString *) issuer
redirectUrl: (NSString *) redirectUrl
redirectUrl: (NSString *) redirectUrl
clientId: (NSString *) clientId
clientId: (NSString *) clientId
clientSecret: (NSString *) clientSecret
clientSecret: (NSString *) clientSecret
refreshToken: (NSString *) refreshToken
refreshToken: (NSString *) refreshToken
scopes: (NSArray *) scopes
scopes: (NSArray *) scopes
additionalParameters: (NSDictionary *_Nullable) additionalParameters
additionalParameters: (NSDictionary *_Nullable) additionalParameters
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
connectionTimeoutSeconds: (double) connectionTimeoutSeconds
connectionTimeoutSeconds: (double) connectionTimeoutSeconds
additionalHeaders: (NSDictionary *_Nullable) additionalHeaders
additionalHeaders: (NSDictionary *_Nullable) additionalHeaders
iosCustomBrowser: (NSString *) iosCustomBrowser
iosCustomBrowser: (NSString *) iosCustomBrowser
resolve:(RCTPromiseResolveBlock) resolve
resolve:(RCTPromiseResolveBlock) resolve
reject: (RCTPromiseRejectBlock) reject)
reject: (RCTPromiseRejectBlock) reject)
{
{
[self configureUrlSession:additionalHeaders sessionTimeout:connectionTimeoutSeconds];
[self configureUrlSession:additionalHeaders sessionTimeout:connectionTimeoutSeconds];
// if we have manually provided configuration, we can use it and skip the OIDC well-known discovery endpoint call
// if we have manually provided configuration, we can use it and skip the OIDC well-known discovery endpoint call
if (serviceConfiguration) {
if (serviceConfiguration) {
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
[self refreshWithConfiguration: configuration
[self refreshWithConfiguration: configuration
redirectUrl: redirectUrl
redirectUrl: redirectUrl
clientId: clientId
clientId: clientId
clientSecret: clientSecret
clientSecret: clientSecret
refreshToken: refreshToken
refreshToken: refreshToken
scopes: scopes
scopes: scopes
additionalParameters: additionalParameters
additionalParameters: additionalParameters
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
} else {
} else {
// otherwise hit up the discovery endpoint
// otherwise hit up the discovery endpoint
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
if (!configuration) {
if (!configuration) {
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
return;
return;
}
}
[self refreshWithConfiguration: configuration
[self refreshWithConfiguration: configuration
redirectUrl: redirectUrl
redirectUrl: redirectUrl
clientId: clientId
clientId: clientId
clientSecret: clientSecret
clientSecret: clientSecret
refreshToken: refreshToken
refreshToken: refreshToken
scopes: scopes
scopes: scopes
additionalParameters: additionalParameters
additionalParameters: additionalParameters
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
}];
}];
}
}
} // end RCT_REMAP_METHOD(refresh,
} // end RCT_REMAP_METHOD(refresh,
RCT_REMAP_METHOD(logout,
RCT_REMAP_METHOD(logout,
issuer: (NSString *) issuer
issuer: (NSString *) issuer
idTokenHint: (NSString *) idTokenHint
idTokenHint: (NSString *) idTokenHint
postLogoutRedirectURL: (NSString *) postLogoutRedirectURL
postLogoutRedirectURL: (NSString *) postLogoutRedirectURL
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration
additionalParameters: (NSDictionary *_Nullable) additionalParameters
additionalParameters: (NSDictionary *_Nullable) additionalParameters
iosCustomBrowser: (NSString *) iosCustomBrowser
iosCustomBrowser: (NSString *) iosCustomBrowser
prefersEphemeralSession: (BOOL *) prefersEphemeralSession
prefersEphemeralSession: (BOOL *) prefersEphemeralSession
resolve:(RCTPromiseResolveBlock) resolve
resolve:(RCTPromiseResolveBlock) resolve
reject: (RCTPromiseRejectBlock) reject)
reject: (RCTPromiseRejectBlock) reject)
{
{
if (serviceConfiguration) {
if (serviceConfiguration) {
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration];
[self endSessionWithConfiguration: configuration
[self endSessionWithConfiguration: configuration
idTokenHint: idTokenHint
idTokenHint: idTokenHint
postLogoutRedirectURL: postLogoutRedirectURL
postLogoutRedirectURL: postLogoutRedirectURL
additionalParameters: additionalParameters
additionalParameters: additionalParameters
iosCustomBrowser: iosCustomBrowser
iosCustomBrowser: iosCustomBrowser
prefersEphemeralSession: prefersEphemeralSession
prefersEphemeralSession: prefersEphemeralSession
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
} else {
} else {
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
[OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer]
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) {
if (!configuration) {
if (!configuration) {
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
reject(@"service_configuration_fetch_error", [error localizedDescription], error);
return;
return;
}
}
[self endSessionWithConfiguration: configuration
[self endSessionWithConfiguration: configuration
idTokenHint: idTokenHint
idTokenHint: idTokenHint
postLogoutRedirectURL: postLogoutRedirectURL
postLogoutRedirectURL: postLogoutRedirectURL
additionalParameters: additionalParameters
additionalParameters: additionalParameters
iosCustomBrowser: iosCustomBrowser
iosCustomBrowser: iosCustomBrowser
prefersEphemeralSession: prefersEphemeralSession
prefersEphemeralSession: prefersEphemeralSession
resolve: resolve
resolve: resolve
reject: reject];
reject: reject];
}];
}];
}
}
} // end RCT_REMAP_METHOD(logout,
} // end RCT_REMAP_METHOD(logout,
/*
/*
* Create a OIDServiceConfiguration from passed serviceConfiguration dictionary
* Create a OIDServiceConfiguration from passed serviceConfiguration dictionary
*/
*/
- (OIDServiceConfiguration *) createServiceConfiguration: (NSDictionary *) serviceConfiguration {
- (OIDServiceConfiguration *) createServiceConfiguration: (NSDictionary *) serviceConfiguration {
NSURL *authorizationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"authorizationEndpoint"]];
NSURL *authorizationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"authorizationEndpoint"]];
NSURL *tokenEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"tokenEndpoint"]];
NSURL *tokenEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"tokenEndpoint"]];
NSURL *registrationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"registrationEndpoint"]];
NSURL *registrationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"registrationEndpoint"]];
NSURL *endSessionEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"endSessionEndpoint"]];
NSURL *endSessionEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"endSessionEndpoint"]];
OIDServiceConfiguration *configuration =
OIDServiceConfiguration *configuration =
[[OIDServiceConfiguration alloc]
[[OIDServiceConfiguration alloc]
initWithAuthorizationEndpoint:authorizationEndpoint
initWithAuthorizationEndpoint:authorizationEndpoint
tokenEndpoint:tokenEndpoint
tokenEndpoint:tokenEndpoint
issuer:nil
issuer:nil
registrationEndpoint:registrationEndpoint
registrationEndpoint:registrationEndpoint
endSessionEndpoint:endSessionEndpoint];
endSessionEndpoint:endSessionEndpoint];
return configuration;
return configuration;
}
}
+ (nullable NSString *)generateCodeVerifier {
+ (nullable NSString *)generateCodeVerifier {
return [OIDTokenUtilities randomURLSafeStringWithSize:kCodeVerifierBytes];
return [OIDTokenUtilities randomURLSafeStringWithSize:kCodeVerifierBytes];
}
}
+ (nullable NSString *)generateState {
+ (nullable NSString *)generateState {
return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes];
return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes];
}
}
+ (nullable NSString *)codeChallengeS256ForVerifier:(NSString *)codeVerifier {
+ (nullable NSString *)codeChallengeS256ForVerifier:(NSString *)codeVerifier {
if (!codeVerifier) {
if (!codeVerifier) {
return nil;
return nil;
}
}
// generates the code_challenge per spec https://tools.ietf.org/html/rfc7636#section-4.2
// generates the code_challenge per spec https://tools.ietf.org/html/rfc7636#section-4.2
// code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
// code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
// NB. the ASCII conversion on the code_verifier entropy was done at time of generation.
// NB. the ASCII conversion on the code_verifier entropy was done at time of generation.
NSData *sha256Verifier = [OIDTokenUtilities sha256:codeVerifier];
NSData *sha256Verifier = [OIDTokenUtilities sha256:codeVerifier];
return [OIDTokenUtilities encodeBase64urlNoPadding:sha256Verifier];
return [OIDTokenUtilities encodeBase64urlNoPadding:sha256Verifier];
}
}
/*
/*
* Perform dynamic client registration with provided OIDServiceConfiguration
* Perform dynamic client registration with provided OIDServiceConfiguration
*/
*/
- (void)registerWithConfiguration: (OIDServiceConfiguration *) configuration
- (void)registerWithConfiguration: (OIDServiceConfiguration *) configuration
redirectUrls: (NSArray *) redirectUrlStrings
redirectUrls: (NSArray *) redirectUrlStrings
responseTypes: (NSArray *) responseTypes
responseTypes: (NSArray *) responseTypes
grantTypes: (NSArray *) grantTypes
grantTypes: (NSArray *) grantTypes
subjectType: (NSString *) subjectType
subjectType: (NSString *) subjectType
tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod
tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod
additionalParameters: (NSDictionary *_Nullable) additionalParameters
additionalParameters: (NSDictionary *_Nullable) additionalParameters
resolve: (RCTPromiseResolveBlock) resolve
resolve: (RCTPromiseResolveBlock) resolve
reject: (RCTPromiseRejectBlock) reject
reject: (RCTPromiseRejectBlock) reject
{
{
NSMutableArray<NSURL *> *redirectUrls = [NSMutableArray arrayWithCapacity:[redirectUrlStrings count]];
NSMutableArray<NSURL *> *redirectUrls = [NSMutableArray arrayWithCapacity:[redirectUrlStrings count]];
for (NSString *urlString in redirectUrlStrings) {
for (NSString *urlString in redirectUrlStrings) {
[redirectUrls addObject:[NSURL URLWithString:urlString]];
[redirectUrls addObject:[NSURL URLWithString:urlString]];
}
}
OIDRegistrationRequest *request =
OIDRegistrationRequest *request =
[[OIDRegistrationRequest alloc] initWithConfiguration:configuration
[[OIDRegistrationRequest alloc] initWithConfiguration:configuration
redirectURIs:redirectUrls
redirectURIs:redirectUrls
responseTypes:responseTypes
responseTypes:responseTypes
grantTypes:grantTypes
grantTypes:grantTypes
subjectType:subjectType
subjectType:subjectType
tokenEndpointAuthMethod:tokenEndpointAuthMethod
tokenEndpointAuthMethod:tokenEndpointAuthMethod
additionalParameters:additionalParameters];
additionalParameters:additionalParameters];
[OIDAuthorizationService performRegistrationRequest:request
[OIDAuthorizationService performRegistrationRequest:request
completion:^(OIDRegistrationResponse *_Nullable response,
completion:^(OIDRegistrationResponse *_Nullable response,
NSError *_Nullable error) {
NSError *_Nullable error) {
if (response) {
if (response) {
resolve([self formatRegistrationResponse:response]);
resolve([self formatRegistrationResponse:response]);
} else {
} else {
reject([self getErrorCode: error defaultCode:@"registration_failed"],
reject([self getErrorCode: error defaultCode:@"registration_failed"],
[self getErrorMessage: error], error);
[self getErrorMessage: error], error);
}
}
}];
}];
}
}
/*
/*
* Authorize a user in exchange for a token with provided OIDServiceConfiguration
* Authorize a user in exchange for a token with provided OIDServiceConfiguration
*/
*/
- (void)authorizeWithConfiguration: (OIDServiceConfiguration *) configuration
- (void)authorizeWithConfiguration: (OIDServiceConfiguration *) configuration
redirectUrl: (NSString *) redirectUrl
redirectUrl: (NSString *) redirectUrl
clientId: (NSString *) clientId
clientId: (NSString *) clientId
clientSecret: (NSString *) clientSecret
clientSecret: (NSString *) clientSecret
scopes: (NSArray *) scopes
scopes: (NSArray *) scopes
useNonce: (BOOL *) useNonce
useNonce: (BOOL *) useNonce
usePKCE: (BOOL *) usePKCE
usePKCE: (BOOL *) usePKCE
additionalParameters: (NSDictionary *_Nullable) additionalParameters
additionalParameters: (NSDictionary *_Nullable) additionalParameters
skipCodeExchange: (BOOL) skipCodeExchange
skipCodeExchange: (BOOL) skipCodeExchange
iosCustomBrowser: (NSString *) iosCustomBrowser
iosCustomBrowser: (NSString *) iosCustomBrowser
prefersEphemeralSession: (BOOL *) prefersEphemeralSession
prefersEphemeralSession: (BOOL *) prefersEphemeralSession
resolve: (RCTPromiseResolveBlock) resolve
resolve: (RCTPromiseResolveBlock) resolve
reject: (RCTPromiseRejectBlock) reject
reject: (RCTPromiseRejectBlock) reject
{
{
NSString *codeVerifier = usePKCE ? [[self class] generateCodeVerifier] : nil;
NSString *codeVerifier = usePKCE ? [[self class] generateCodeVerifier] : nil;
NSString *codeChallenge = usePKCE ? [[self class] codeChallengeS256ForVerifier:codeVerifier] : nil;
NSString *codeChallenge = usePKCE ? [[self class] codeChallengeS256ForVerifier:codeVerifier] : nil;
NSString *nonce = useNonce ? additionalParameters[@"nonce"]? additionalParameters[@"nonce"]: [[self class] generateState] : nil ;
NSString *nonce = useNonce ? additionalParameters[@"nonce"]? additionalParameters[@"nonce"]: [[self class] generateState] : nil ;
// builds authentication request
// builds authentication request
OIDAuthorizationRequest *request =
OIDAuthorizationRequest *request =
[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
[[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
clientId:clientId
clientId:clientId
clientSecret:clientSecret
clientSecret:clientSecret
scope:[OIDScopeUtilities scopesWithArray:scopes]
scope:[OIDScopeUtilities scopesWithArray:scopes]
redirectURL:[NSURL URLWithString:redirectUrl]
redirectURL:[NSURL URLWithString:redirectUrl]
responseType:OIDResponseTypeCode
responseType:OIDResponseTypeCode
state: additionalParameters[@"state"] ? additionalParameters[@"state"] : [[self class] generateState]
state: additionalParameters[@"state"] ? additionalParameters[@"state"] : [[self class] generateState]
nonce:nonce
nonce:nonce
codeVerifier:codeVerifier
codeVerifier:codeVerifier
codeChallenge:codeChallenge
codeChallenge:codeChallenge
codeChallengeMethod: usePKCE ? OIDOAuthorizationRequestCodeChallengeMethodS256 : nil
codeChallengeMethod: usePKCE ? OIDOAuthorizationRequestCodeChallengeMethodS256 : nil
additionalParameters:additionalParameters];
additionalParameters:additionalParameters];
// performs authentication request
// performs authentication request
id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate;
id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate;
if (![[appDelegate class] conformsToProtocol:@protocol(RNAppAuthAuthorizationFlowManager)]) {
if (![[appDelegate class] conformsToProtocol:@protocol(RNAppAuthAuthorizationFlowManager)]) {
[NSException raise:@"RNAppAuth Missing protocol conformance"
[NSException raise:@"RNAppAuth Missing protocol conformance"
format:@"%@ does not conform to RNAppAuthAuthorizationFlowManager", appDelegate];
format:@"%@ does not conform to RNAppAuthAuthorizationFlowManager", appDelegate];
}
}
appDelegate.authorizationFlowManagerDelegate = self;
appDelegate.authorizationFlowManagerDelegate = self;
__weak typeof(self) weakSelf = self;
__weak typeof(self) weakSelf = self;
rnAppAuthTaskId = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{
rnAppAuthTaskId = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{
[UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId];
[UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId];
rnAppAuthTaskId = UIBackgroundTaskInvalid;
rnAppAuthTaskId = UIBackgroundTaskInvalid;
}];
}];
UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController;
UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController;
#if TARGET_OS_MACCATALYST
#if TARGET_OS_MACCATALYST
id<OIDExternalUserAgent> externalUserAgent = nil;
id<OIDExternalUserAgent> externalUserAgent = nil;
#elif TARGET_OS_IOS
#elif TARGET_OS_IOS
id<OIDExternalUserAgent> externalUserAgent = iosCustomBrowser != nil ? [self getCustomBrowser: iosCustomBrowser] : nil;
id<OIDExternalUserAgent> externalUserAgent = iosCustomBrowser != nil ? [self getCustomBrowser: iosCustomBrowser] : nil;
#endif
#endif
OIDAuthorizationCallback callback = ^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) {
OIDAuthorizationCallback callback = ^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) {
typeof(self) strongSelf = weakSelf;
typeof(self) strongSelf = weakSelf;
strongSelf->_currentSession = nil;
strongSelf->_currentSession = nil;
[UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId];
[UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId];
rnAppAuthTaskId = UIBackgroundTaskInvalid;
rnAppAuthTaskId = UIBackgroundTaskInvalid;
if (authorizationResponse) {
if (authorizationResponse) {
resolve([self formatAuthorizationResponse:authorizationResponse withCodeVerifier:codeVerifier]);
resolve([
} else {
reject([self getErrorCode: error defaultCode:@"authentication_failed"],
[self getErrorMessage: error], error);
}
};
if (skipCodeExchange) {
if(externalUserAgent != nil) {
_currentSession = [OIDAuthorizationService presentAuthorizationRequest:request
externalUserAgent:externalUserAgent
callback:callback];
} else {
if (@available(iOS 13, *)) {
_currentSession = [OIDAuthorizationService presentAuthorizationRequest:request
presentingViewController:presentingViewController
prefersEphemeralSession:prefersEphemeralSession
callback:callback];
} else {
_currentSession = [OIDAuthorizationService presentAuthorizationRequest:request
presentingViewController:presentingViewController
callback:callback];
}
}
} else {
OIDAuthStateAuthorizationCallback callback = ^(
OI