Diff
checker
Texto
Texto
Imágenes
Documentos
Excel
Carpetas
Legal
Enterprise
Aplicación de escritorio
Precios
Iniciar sesión
Descargar Diffchecker Desktop
Comparar texto
Encuentra la diferencia entre dos archivos de texto
Herramientas
Historial
Editor live
Ocultar sin cambios
Sin ajuste de línea
Vista
Dividido
Unificado
Nivel de detalle
Inteligente
Palabra
Letra
Resaltado de sintaxis
Elegir sintaxis
Ignorar
Transformar texto
Ir al primer cambio
Editar entrada
Diffchecker Desktop
La forma más segura de usar Diffchecker. ¡Obtén la app de Diffchecker Desktop: tus diffs nunca salen de tu computadora!
Obtener Desktop
RNAppAuth.m (react-native-app-auth@7.1.3)
Creado
hace 2 años
El diff nunca expira
Borrar
Exportar
Compartir
Explicar
28 eliminaciones
Líneas
Total
Eliminado
Caracteres
Total
Eliminado
Para continuar usando esta función, actualice a
Diff
checker
Pro
Ver precios
413 líneas
Copiar todo
25 adiciones
Líneas
Total
Añadido
Caracteres
Total
Añadido
Para continuar usando esta función, actualice a
Diff
checker
Pro
Ver precios
411 líneas
Copiar todo
#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;
}
}
Copiar
Copiado
Copiar
Copiado
@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()
Copiar
Copiado
Copiar
Copiado
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)
{
{
Copiar
Copiado
Copiar
Copiado
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);
Copiar
Copiado
Copiar
Copiado
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) {
Copiar
Copiado
Copiar
Copiado
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
Diferencias guardadas
Texto original
Abrir archivo
#import "RNAppAuth.h" #if __has_include(<AppAuth/AppAuth.h>) #import <AppAuth/AppAuth.h> #else #import "AppAuth.h" #endif #import <React/RCTLog.h> #import <React/RCTConvert.h> #import "RNAppAuthAuthorizationFlowManager.h" @interface RNAppAuth()<RNAppAuthAuthorizationFlowManagerDelegate> { id<OIDExternalUserAgentSession> _currentSession; } @end @implementation RNAppAuth -(BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url { return [_currentSession resumeExternalUserAgentFlowWithURL:url]; } - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } UIBackgroundTaskIdentifier rnAppAuthTaskId; /*! @brief Number of random bytes generated for the @ state. */ static NSUInteger const kStateSizeBytes = 32; /*! @brief Number of random bytes generated for the @ codeVerifier. */ static NSUInteger const kCodeVerifierBytes = 32; RCT_EXPORT_MODULE() RCT_REMAP_METHOD(register, issuer: (NSString *) issuer redirectUrls: (NSArray *) redirectUrls responseTypes: (NSArray *) responseTypes grantTypes: (NSArray *) grantTypes subjectType: (NSString *) subjectType tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod additionalParameters: (NSDictionary *_Nullable) additionalParameters serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration connectionTimeoutSeconds: (double) connectionTimeoutSeconds additionalHeaders: (NSDictionary *_Nullable) additionalHeaders resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { [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 (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self registerWithConfiguration: configuration redirectUrls: redirectUrls responseTypes: responseTypes grantTypes: grantTypes subjectType: subjectType tokenEndpointAuthMethod: tokenEndpointAuthMethod additionalParameters: additionalParameters resolve: resolve reject: reject]; } else { [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self registerWithConfiguration: configuration redirectUrls: redirectUrls responseTypes: responseTypes grantTypes: grantTypes subjectType: subjectType tokenEndpointAuthMethod: tokenEndpointAuthMethod additionalParameters: additionalParameters resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(register, RCT_REMAP_METHOD(authorize, issuer: (NSString *) issuer redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret scopes: (NSArray *) scopes additionalParameters: (NSDictionary *_Nullable) additionalParameters serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration skipCodeExchange: (BOOL) skipCodeExchange connectionTimeoutSeconds: (double) connectionTimeoutSeconds additionalHeaders: (NSDictionary *_Nullable) additionalHeaders useNonce: (BOOL *) useNonce usePKCE: (BOOL *) usePKCE iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { [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 (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self authorizeWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret scopes: scopes useNonce: useNonce usePKCE: usePKCE additionalParameters: additionalParameters skipCodeExchange: skipCodeExchange iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; } else { [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self authorizeWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret scopes: scopes useNonce: useNonce usePKCE: usePKCE additionalParameters: additionalParameters skipCodeExchange: skipCodeExchange iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(authorize, RCT_REMAP_METHOD(refresh, issuer: (NSString *) issuer redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret refreshToken: (NSString *) refreshToken scopes: (NSArray *) scopes additionalParameters: (NSDictionary *_Nullable) additionalParameters serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration connectionTimeoutSeconds: (double) connectionTimeoutSeconds additionalHeaders: (NSDictionary *_Nullable) additionalHeaders iosCustomBrowser: (NSString *) iosCustomBrowser resolve:(RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { [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 (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self refreshWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret refreshToken: refreshToken scopes: scopes additionalParameters: additionalParameters resolve: resolve reject: reject]; } else { // otherwise hit up the discovery endpoint [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self refreshWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret refreshToken: refreshToken scopes: scopes additionalParameters: additionalParameters resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(refresh, RCT_REMAP_METHOD(logout, issuer: (NSString *) issuer idTokenHint: (NSString *) idTokenHint postLogoutRedirectURL: (NSString *) postLogoutRedirectURL serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration additionalParameters: (NSDictionary *_Nullable) additionalParameters iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve:(RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { if (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self endSessionWithConfiguration: configuration idTokenHint: idTokenHint postLogoutRedirectURL: postLogoutRedirectURL additionalParameters: additionalParameters iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; } else { [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self endSessionWithConfiguration: configuration idTokenHint: idTokenHint postLogoutRedirectURL: postLogoutRedirectURL additionalParameters: additionalParameters iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(logout, /* * Create a OIDServiceConfiguration from passed serviceConfiguration dictionary */ - (OIDServiceConfiguration *) createServiceConfiguration: (NSDictionary *) serviceConfiguration { NSURL *authorizationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"authorizationEndpoint"]]; NSURL *tokenEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"tokenEndpoint"]]; NSURL *registrationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"registrationEndpoint"]]; NSURL *endSessionEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"endSessionEndpoint"]]; OIDServiceConfiguration *configuration = [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpoint tokenEndpoint:tokenEndpoint issuer:nil registrationEndpoint:registrationEndpoint endSessionEndpoint:endSessionEndpoint]; return configuration; } + (nullable NSString *)generateCodeVerifier { return [OIDTokenUtilities randomURLSafeStringWithSize:kCodeVerifierBytes]; } + (nullable NSString *)generateState { return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes]; } + (nullable NSString *)codeChallengeS256ForVerifier:(NSString *)codeVerifier { if (!codeVerifier) { return nil; } // generates the code_challenge per spec https://tools.ietf.org/html/rfc7636#section-4.2 // code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) // NB. the ASCII conversion on the code_verifier entropy was done at time of generation. NSData *sha256Verifier = [OIDTokenUtilities sha256:codeVerifier]; return [OIDTokenUtilities encodeBase64urlNoPadding:sha256Verifier]; } /* * Perform dynamic client registration with provided OIDServiceConfiguration */ - (void)registerWithConfiguration: (OIDServiceConfiguration *) configuration redirectUrls: (NSArray *) redirectUrlStrings responseTypes: (NSArray *) responseTypes grantTypes: (NSArray *) grantTypes subjectType: (NSString *) subjectType tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod additionalParameters: (NSDictionary *_Nullable) additionalParameters resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { NSMutableArray<NSURL *> *redirectUrls = [NSMutableArray arrayWithCapacity:[redirectUrlStrings count]]; for (NSString *urlString in redirectUrlStrings) { [redirectUrls addObject:[NSURL URLWithString:urlString]]; } OIDRegistrationRequest *request = [[OIDRegistrationRequest alloc] initWithConfiguration:configuration redirectURIs:redirectUrls responseTypes:responseTypes grantTypes:grantTypes subjectType:subjectType tokenEndpointAuthMethod:tokenEndpointAuthMethod additionalParameters:additionalParameters]; [OIDAuthorizationService performRegistrationRequest:request completion:^(OIDRegistrationResponse *_Nullable response, NSError *_Nullable error) { if (response) { resolve([self formatRegistrationResponse:response]); } else { reject([self getErrorCode: error defaultCode:@"registration_failed"], [self getErrorMessage: error], error); } }]; } /* * Authorize a user in exchange for a token with provided OIDServiceConfiguration */ - (void)authorizeWithConfiguration: (OIDServiceConfiguration *) configuration redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret scopes: (NSArray *) scopes useNonce: (BOOL *) useNonce usePKCE: (BOOL *) usePKCE additionalParameters: (NSDictionary *_Nullable) additionalParameters skipCodeExchange: (BOOL) skipCodeExchange iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { NSString *codeVerifier = usePKCE ? [[self class] generateCodeVerifier] : nil; NSString *codeChallenge = usePKCE ? [[self class] codeChallengeS256ForVerifier:codeVerifier] : nil; NSString *nonce = useNonce ? additionalParameters[@"nonce"]? additionalParameters[@"nonce"]: [[self class] generateState] : nil ; // builds authentication request OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration clientId:clientId clientSecret:clientSecret scope:[OIDScopeUtilities scopesWithArray:scopes] redirectURL:[NSURL URLWithString:redirectUrl] responseType:OIDResponseTypeCode state: additionalParameters[@"state"] ? additionalParameters[@"state"] : [[self class] generateState] nonce:nonce codeVerifier:codeVerifier codeChallenge:codeChallenge codeChallengeMethod: usePKCE ? OIDOAuthorizationRequestCodeChallengeMethodS256 : nil additionalParameters:additionalParameters]; // performs authentication request id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate; if (![[appDelegate class] conformsToProtocol:@protocol(RNAppAuthAuthorizationFlowManager)]) { [NSException raise:@"RNAppAuth Missing protocol conformance" format:@"%@ does not conform to RNAppAuthAuthorizationFlowManager", appDelegate]; } appDelegate.authorizationFlowManagerDelegate = self; __weak typeof(self) weakSelf = self; rnAppAuthTaskId = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{ [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; }]; UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController; #if TARGET_OS_MACCATALYST id<OIDExternalUserAgent> externalUserAgent = nil; #elif TARGET_OS_IOS id<OIDExternalUserAgent> externalUserAgent = iosCustomBrowser != nil ? [self getCustomBrowser: iosCustomBrowser] : nil; #endif OIDAuthorizationCallback callback = ^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) { typeof(self) strongSelf = weakSelf; strongSelf->_currentSession = nil; [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; if (authorizationResponse) { resolve([self formatAuthorizationResponse:authorizationResponse withCodeVerifier:codeVerifier]); } 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 = ^( OIDAuthState *_Nullable authState, NSError *_Nullable error ) { typeof(self) strongSelf = weakSelf; strongSelf->_currentSession = nil; [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; if (authState) { resolve([self formatResponse:authState.lastTokenResponse withAuthResponse:authState.lastAuthorizationResponse]); } else { reject([self getErrorCode: error defaultCode:@"authentication_failed"], [self getErrorMessage: error], error); } }; if(externalUserAgent != nil) { _currentSession = [OIDAuthState authStateByPresentingAuthorizationRequest:request externalUserAgent:externalUserAgent callback:callback]; } else { if (@available(iOS 13, *)) { _currentSession = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:presentingViewController prefersEphemeralSession:prefersEphemeralSession callback:callback]; } else { _currentSession = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:presentingViewController callback:callback]; } } } } /* * Refresh a token with provided OIDServiceConfiguration */ - (void)refreshWithConfiguration: (OIDServiceConfiguration *)configuration redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret refreshToken: (NSString *) refreshToken scopes: (NSArray *) scopes additionalParameters: (NSDictionary *_Nullable) additionalParameters resolve:(RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { OIDTokenRequest *tokenRefreshRequest = [[OIDTokenRequest alloc] initWithConfiguration:configuration grantType:@"refresh_token" authorizationCode:nil redirectURL:[NSURL URLWithString:redirectUrl] clientID:clientId clientSecret:clientSecret scopes:scopes refreshToken:refreshToken codeVerifier:nil additionalParameters:additionalParameters]; [OIDAuthorizationService performTokenRequest:tokenRefreshRequest callback:^(OIDTokenResponse *_Nullable response, NSError *_Nullable error) { if (response) { resolve([self formatResponse:response]); } else { reject([self getErrorCode: error defaultCode:@"token_refresh_failed"], [self getErrorMessage: error], error); } }]; } - (void)endSessionWithConfiguration: (OIDServiceConfiguration *) configuration idTokenHint: (NSString *) idTokenHint postLogoutRedirectURL: (NSString *) postLogoutRedirectURL additionalParameters: (NSDictionary *_Nullable) additionalParameters iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { OIDEndSessionRequest *endSessionRequest = [[OIDEndSessionRequest alloc] initWithConfiguration: configuration idTokenHint: idTokenHint postLogoutRedirectURL: [NSURL URLWithString:postLogoutRedirectURL] additionalParameters: additionalParameters]; id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate; if (![[appDelegate class] conformsToProtocol:@protocol(RNAppAuthAuthorizationFlowManager)]) { [NSException raise:@"RNAppAuth Missing protocol conformance" format:@"%@ does not conform to RNAppAuthAuthorizationFlowManager", appDelegate]; } appDelegate.authorizationFlowManagerDelegate = self; __weak typeof(self) weakSelf = self; rnAppAuthTaskId = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{ [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; }]; UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController; #if TARGET_OS_MACCATALYST id<OIDExternalUserAgent> externalUserAgent = nil; #elif TARGET_OS_IOS id<OIDExternalUserAgent> externalUserAgent = iosCustomBrowser != nil ? [self getCustomBrowser: iosCustomBrowser] : [self getExternalUserAgentWithPresentingViewController:presentingViewController prefersEphemeralSession:prefersEphemeralSession]; #endif _currentSession = [OIDAuthorizationService presentEndSessionRequest: endSessionRequest externalUserAgent: externalUserAgent callback: ^(OIDEndSessionResponse *_Nullable response, NSError *_Nullable error) { typeof(self) strongSelf = weakSelf; strongSelf->_currentSession = nil; [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; if (response) { resolve([self formatEndSessionResponse:response]); } else { reject([self getErrorCode: error defaultCode:@"end_session_failed"], [self getErrorMessage: error], error); } }]; } - (void)configureUrlSession: (NSDictionary*) headers sessionTimeout: (double) sessionTimeout{ NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; if (headers != nil) { configuration.HTTPAdditionalHeaders = headers; } configuration.timeoutIntervalForRequest = sessionTimeout; NSURLSession* session = [NSURLSession sessionWithConfiguration:configuration]; [OIDURLSessionProvider setSession:session]; } /* * Take raw OIDAuthorizationResponse and turn it to response format to pass to JavaScript caller */ - (NSDictionary *)formatAuthorizationResponse: (OIDAuthorizationResponse *) response withCodeVerifier: (NSString *) codeVerifier { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; if (codeVerifier == nil) { return @{@"authorizationCode": response.authorizationCode ? response.authorizationCode : @"", @"state": response.state ? response.state : @"", @"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"tokenType": response.tokenType ? response.tokenType : @"", @"idToken": response.idToken ? response.idToken : @"", @"scopes": response.scope ? [response.scope componentsSeparatedByString:@" "] : [NSArray new], @"additionalParameters": response.additionalParameters, }; } else { return @{@"authorizationCode": response.authorizationCode ? response.authorizationCode : @"", @"state": response.state ? response.state : @"", @"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"tokenType": response.tokenType ? response.tokenType : @"", @"idToken": response.idToken ? response.idToken : @"", @"scopes": response.scope ? [response.scope componentsSeparatedByString:@" "] : [NSArray new], @"additionalParameters": response.additionalParameters, @"codeVerifier": codeVerifier }; } } /* * Take raw OIDTokenResponse and turn it to a token response format to pass to JavaScript caller */ - (NSDictionary*)formatResponse: (OIDTokenResponse*) response { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return @{@"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"additionalParameters": response.additionalParameters, @"idToken": response.idToken ? response.idToken : @"", @"refreshToken": response.refreshToken ? response.refreshToken : @"", @"tokenType": response.tokenType ? response.tokenType : @"", }; } /* * Take raw OIDTokenResponse and additional paramaeters from an OIDAuthorizationResponse * and turn them into an extended token response format to pass to JavaScript caller */ - (NSDictionary*)formatResponse: (OIDTokenResponse*) response withAuthResponse:(OIDAuthorizationResponse*) authResponse { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return @{@"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"authorizeAdditionalParameters": authResponse.additionalParameters, @"tokenAdditionalParameters": response.additionalParameters, @"idToken": response.idToken ? response.idToken : @"", @"refreshToken": response.refreshToken ? response.refreshToken : @"", @"tokenType": response.tokenType ? response.tokenType : @"", @"scopes": authResponse.scope ? [authResponse.scope componentsSeparatedByString:@" "] : [NSArray new], }; } - (NSDictionary*)formatRegistrationResponse: (OIDRegistrationResponse*) response { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return @{@"clientId": response.clientID, @"additionalParameters": response.additionalParameters, @"clientIdIssuedAt": response.clientIDIssuedAt ? [dateFormat stringFromDate:response.clientIDIssuedAt] : @"", @"clientSecret": response.clientSecret ? response.clientSecret : @"", @"clientSecretExpiresAt": response.clientSecretExpiresAt ? [dateFormat stringFromDate:response.clientSecretExpiresAt] : @"", @"registrationAccessToken": response.registrationAccessToken ? response.registrationAccessToken : @"", @"registrationClientUri": response.registrationClientURI ? response.registrationClientURI : @"", @"tokenEndpointAuthMethod": response.tokenEndpointAuthenticationMethod ? response.tokenEndpointAuthenticationMethod : @"", }; } - (NSDictionary*)formatEndSessionResponse: (OIDEndSessionResponse*)response { return @{@"state": response.state ? response.state : @"", @"idTokenHint": response.request.idTokenHint, @"postLogoutRedirectUri": response.request.postLogoutRedirectURL.absoluteString }; } - (NSString*)getErrorCode: (NSError*) error defaultCode: (NSString *) defaultCode { if ([[error domain] isEqualToString:OIDOAuthAuthorizationErrorDomain]) { switch ([error code]) { case OIDErrorCodeOAuthAuthorizationInvalidRequest: return @"invalid_request"; case OIDErrorCodeOAuthAuthorizationUnauthorizedClient: return @"unauthorized_client"; case OIDErrorCodeOAuthAuthorizationAccessDenied: return @"access_denied"; case OIDErrorCodeOAuthAuthorizationUnsupportedResponseType: return @"unsupported_response_type"; case OIDErrorCodeOAuthAuthorizationAuthorizationInvalidScope: return @"invalid_scope"; case OIDErrorCodeOAuthAuthorizationServerError: return @"server_error"; case OIDErrorCodeOAuthAuthorizationTemporarilyUnavailable: return @"temporarily_unavailable"; } } else if ([[error domain] isEqualToString:OIDOAuthTokenErrorDomain]) { switch ([error code]) { case OIDErrorCodeOAuthTokenInvalidRequest: return @"invalid_request"; case OIDErrorCodeOAuthTokenInvalidClient: return @"invalid_client"; case OIDErrorCodeOAuthTokenInvalidGrant: return @"invalid_grant"; case OIDErrorCodeOAuthTokenUnauthorizedClient: return @"unauthorized_client"; case OIDErrorCodeOAuthTokenUnsupportedGrantType: return @"unsupported_grant_type"; case OIDErrorCodeOAuthTokenInvalidScope: return @"invalid_scope"; } } else if ([[error domain] isEqualToString:OIDOAuthRegistrationErrorDomain]) { switch ([error code]) { case OIDErrorCodeOAuthRegistrationInvalidRequest: return @"invalid_request"; case OIDErrorCodeOAuthRegistrationInvalidRedirectURI: return @"invalid_redirect_uri"; case OIDErrorCodeOAuthRegistrationInvalidClientMetadata: return @"invalid_client_metadata"; } } return defaultCode; } #if !TARGET_OS_MACCATALYST - (id<OIDExternalUserAgent>)getCustomBrowser: (NSString *) browserType { typedef id<OIDExternalUserAgent> (^BrowserBlock)(void); NSDictionary *browsers = @{ @"safari": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserSafari]; }, @"chrome": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserChrome]; }, @"opera": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserOpera]; }, @"firefox": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserFirefox]; } }; BrowserBlock browser = browsers[browserType]; return browser(); } #endif - (NSString*)getErrorMessage: (NSError*) error { NSDictionary * userInfo = [error userInfo]; if (userInfo && userInfo[OIDOAuthErrorResponseErrorKey] && userInfo[OIDOAuthErrorResponseErrorKey][OIDOAuthErrorFieldErrorDescription]) { return userInfo[OIDOAuthErrorResponseErrorKey][OIDOAuthErrorFieldErrorDescription]; } else { return [error localizedDescription]; } } - (id<OIDExternalUserAgent>)getExternalUserAgentWithPresentingViewController: (UIViewController *)presentingViewController prefersEphemeralSession: (BOOL *) prefersEphemeralSession { id<OIDExternalUserAgent> externalUserAgent; #if TARGET_OS_MACCATALYST externalUserAgent = [[OIDExternalUserAgentCatalyst alloc] initWithPresentingViewController:presentingViewController]; #elif TARGET_OS_IOS if (@available(iOS 13, *)) { externalUserAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController: presentingViewController prefersEphemeralSession:prefersEphemeralSession]; } else { externalUserAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController: presentingViewController]; } #elif TARGET_OS_OSX externalUserAgent = [[OIDExternalUserAgentMac alloc] init]; #endif return externalUserAgent; } @end
Texto modificado
Abrir archivo
#import "RNAppAuth.h" #if __has_include(<AppAuth/AppAuth.h>) #import <AppAuth/AppAuth.h> #else #import "AppAuth.h" #endif #import <React/RCTLog.h> #import <React/RCTConvert.h> #import "RNAppAuthAuthorizationFlowManager.h" @interface RNAppAuth()<RNAppAuthAuthorizationFlowManagerDelegate> { id<OIDExternalUserAgentSession> _currentSession; } @property (nonatomic, copy) RCTPromiseRejectBlock authorizeRejectBlock; @end @implementation RNAppAuth -(BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)url { return [_currentSession resumeExternalUserAgentFlowWithURL:url]; } - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } UIBackgroundTaskIdentifier rnAppAuthTaskId; /*! @brief Number of random bytes generated for the @ state. */ static NSUInteger const kStateSizeBytes = 32; /*! @brief Number of random bytes generated for the @ codeVerifier. */ static NSUInteger const kCodeVerifierBytes = 32; 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, issuer: (NSString *) issuer redirectUrls: (NSArray *) redirectUrls responseTypes: (NSArray *) responseTypes grantTypes: (NSArray *) grantTypes subjectType: (NSString *) subjectType tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod additionalParameters: (NSDictionary *_Nullable) additionalParameters serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration connectionTimeoutSeconds: (double) connectionTimeoutSeconds additionalHeaders: (NSDictionary *_Nullable) additionalHeaders resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { [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 (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self registerWithConfiguration: configuration redirectUrls: redirectUrls responseTypes: responseTypes grantTypes: grantTypes subjectType: subjectType tokenEndpointAuthMethod: tokenEndpointAuthMethod additionalParameters: additionalParameters resolve: resolve reject: reject]; } else { [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self registerWithConfiguration: configuration redirectUrls: redirectUrls responseTypes: responseTypes grantTypes: grantTypes subjectType: subjectType tokenEndpointAuthMethod: tokenEndpointAuthMethod additionalParameters: additionalParameters resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(register, RCT_REMAP_METHOD(authorize, issuer: (NSString *) issuer redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret scopes: (NSArray *) scopes additionalParameters: (NSDictionary *_Nullable) additionalParameters serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration skipCodeExchange: (BOOL) skipCodeExchange connectionTimeoutSeconds: (double) connectionTimeoutSeconds additionalHeaders: (NSDictionary *_Nullable) additionalHeaders useNonce: (BOOL *) useNonce usePKCE: (BOOL *) usePKCE iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { self.authorizeRejectBlock = reject; [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 (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self authorizeWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret scopes: scopes useNonce: useNonce usePKCE: usePKCE additionalParameters: additionalParameters skipCodeExchange: skipCodeExchange iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; } else { [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks. return; } [self authorizeWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret scopes: scopes useNonce: useNonce usePKCE: usePKCE additionalParameters: additionalParameters skipCodeExchange: skipCodeExchange iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(authorize, RCT_REMAP_METHOD(refresh, issuer: (NSString *) issuer redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret refreshToken: (NSString *) refreshToken scopes: (NSArray *) scopes additionalParameters: (NSDictionary *_Nullable) additionalParameters serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration connectionTimeoutSeconds: (double) connectionTimeoutSeconds additionalHeaders: (NSDictionary *_Nullable) additionalHeaders iosCustomBrowser: (NSString *) iosCustomBrowser resolve:(RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { [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 (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self refreshWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret refreshToken: refreshToken scopes: scopes additionalParameters: additionalParameters resolve: resolve reject: reject]; } else { // otherwise hit up the discovery endpoint [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self refreshWithConfiguration: configuration redirectUrl: redirectUrl clientId: clientId clientSecret: clientSecret refreshToken: refreshToken scopes: scopes additionalParameters: additionalParameters resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(refresh, RCT_REMAP_METHOD(logout, issuer: (NSString *) issuer idTokenHint: (NSString *) idTokenHint postLogoutRedirectURL: (NSString *) postLogoutRedirectURL serviceConfiguration: (NSDictionary *_Nullable) serviceConfiguration additionalParameters: (NSDictionary *_Nullable) additionalParameters iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve:(RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject) { if (serviceConfiguration) { OIDServiceConfiguration *configuration = [self createServiceConfiguration:serviceConfiguration]; [self endSessionWithConfiguration: configuration idTokenHint: idTokenHint postLogoutRedirectURL: postLogoutRedirectURL additionalParameters: additionalParameters iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; } else { [OIDAuthorizationService discoverServiceConfigurationForIssuer:[NSURL URLWithString:issuer] completion:^(OIDServiceConfiguration *_Nullable configuration, NSError *_Nullable error) { if (!configuration) { reject(@"service_configuration_fetch_error", [error localizedDescription], error); return; } [self endSessionWithConfiguration: configuration idTokenHint: idTokenHint postLogoutRedirectURL: postLogoutRedirectURL additionalParameters: additionalParameters iosCustomBrowser: iosCustomBrowser prefersEphemeralSession: prefersEphemeralSession resolve: resolve reject: reject]; }]; } } // end RCT_REMAP_METHOD(logout, /* * Create a OIDServiceConfiguration from passed serviceConfiguration dictionary */ - (OIDServiceConfiguration *) createServiceConfiguration: (NSDictionary *) serviceConfiguration { NSURL *authorizationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"authorizationEndpoint"]]; NSURL *tokenEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"tokenEndpoint"]]; NSURL *registrationEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"registrationEndpoint"]]; NSURL *endSessionEndpoint = [NSURL URLWithString: [serviceConfiguration objectForKey:@"endSessionEndpoint"]]; OIDServiceConfiguration *configuration = [[OIDServiceConfiguration alloc] initWithAuthorizationEndpoint:authorizationEndpoint tokenEndpoint:tokenEndpoint issuer:nil registrationEndpoint:registrationEndpoint endSessionEndpoint:endSessionEndpoint]; return configuration; } + (nullable NSString *)generateCodeVerifier { return [OIDTokenUtilities randomURLSafeStringWithSize:kCodeVerifierBytes]; } + (nullable NSString *)generateState { return [OIDTokenUtilities randomURLSafeStringWithSize:kStateSizeBytes]; } + (nullable NSString *)codeChallengeS256ForVerifier:(NSString *)codeVerifier { if (!codeVerifier) { return nil; } // generates the code_challenge per spec https://tools.ietf.org/html/rfc7636#section-4.2 // code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) // NB. the ASCII conversion on the code_verifier entropy was done at time of generation. NSData *sha256Verifier = [OIDTokenUtilities sha256:codeVerifier]; return [OIDTokenUtilities encodeBase64urlNoPadding:sha256Verifier]; } /* * Perform dynamic client registration with provided OIDServiceConfiguration */ - (void)registerWithConfiguration: (OIDServiceConfiguration *) configuration redirectUrls: (NSArray *) redirectUrlStrings responseTypes: (NSArray *) responseTypes grantTypes: (NSArray *) grantTypes subjectType: (NSString *) subjectType tokenEndpointAuthMethod: (NSString *) tokenEndpointAuthMethod additionalParameters: (NSDictionary *_Nullable) additionalParameters resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { NSMutableArray<NSURL *> *redirectUrls = [NSMutableArray arrayWithCapacity:[redirectUrlStrings count]]; for (NSString *urlString in redirectUrlStrings) { [redirectUrls addObject:[NSURL URLWithString:urlString]]; } OIDRegistrationRequest *request = [[OIDRegistrationRequest alloc] initWithConfiguration:configuration redirectURIs:redirectUrls responseTypes:responseTypes grantTypes:grantTypes subjectType:subjectType tokenEndpointAuthMethod:tokenEndpointAuthMethod additionalParameters:additionalParameters]; [OIDAuthorizationService performRegistrationRequest:request completion:^(OIDRegistrationResponse *_Nullable response, NSError *_Nullable error) { if (response) { resolve([self formatRegistrationResponse:response]); } else { reject([self getErrorCode: error defaultCode:@"registration_failed"], [self getErrorMessage: error], error); } }]; } /* * Authorize a user in exchange for a token with provided OIDServiceConfiguration */ - (void)authorizeWithConfiguration: (OIDServiceConfiguration *) configuration redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret scopes: (NSArray *) scopes useNonce: (BOOL *) useNonce usePKCE: (BOOL *) usePKCE additionalParameters: (NSDictionary *_Nullable) additionalParameters skipCodeExchange: (BOOL) skipCodeExchange iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { NSString *codeVerifier = usePKCE ? [[self class] generateCodeVerifier] : nil; NSString *codeChallenge = usePKCE ? [[self class] codeChallengeS256ForVerifier:codeVerifier] : nil; NSString *nonce = useNonce ? additionalParameters[@"nonce"]? additionalParameters[@"nonce"]: [[self class] generateState] : nil ; // builds authentication request OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration clientId:clientId clientSecret:clientSecret scope:[OIDScopeUtilities scopesWithArray:scopes] redirectURL:[NSURL URLWithString:redirectUrl] responseType:OIDResponseTypeCode state: additionalParameters[@"state"] ? additionalParameters[@"state"] : [[self class] generateState] nonce:nonce codeVerifier:codeVerifier codeChallenge:codeChallenge codeChallengeMethod: usePKCE ? OIDOAuthorizationRequestCodeChallengeMethodS256 : nil additionalParameters:additionalParameters]; // performs authentication request id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate; if (![[appDelegate class] conformsToProtocol:@protocol(RNAppAuthAuthorizationFlowManager)]) { [NSException raise:@"RNAppAuth Missing protocol conformance" format:@"%@ does not conform to RNAppAuthAuthorizationFlowManager", appDelegate]; } appDelegate.authorizationFlowManagerDelegate = self; __weak typeof(self) weakSelf = self; rnAppAuthTaskId = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{ [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; }]; UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController; #if TARGET_OS_MACCATALYST id<OIDExternalUserAgent> externalUserAgent = nil; #elif TARGET_OS_IOS id<OIDExternalUserAgent> externalUserAgent = iosCustomBrowser != nil ? [self getCustomBrowser: iosCustomBrowser] : nil; #endif OIDAuthorizationCallback callback = ^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) { typeof(self) strongSelf = weakSelf; strongSelf->_currentSession = nil; [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; if (authorizationResponse) { resolve([self formatAuthorizationResponse:authorizationResponse withCodeVerifier:codeVerifier]); self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks. } else { reject([self getErrorCode: error defaultCode:@"authentication_failed"], [self getErrorMessage: error], error); self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks. } }; 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 = ^( OIDAuthState *_Nullable authState, NSError *_Nullable error ) { typeof(self) strongSelf = weakSelf; strongSelf->_currentSession = nil; [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; if (authState) { resolve([self formatResponse:authState.lastTokenResponse withAuthResponse:authState.lastAuthorizationResponse]); self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks. } else { reject([self getErrorCode: error defaultCode:@"authentication_failed"], [self getErrorMessage: error], error); self.authorizeRejectBlock = nil; // Clear the block to avoid memory leaks. } }; if(externalUserAgent != nil) { _currentSession = [OIDAuthState authStateByPresentingAuthorizationRequest:request externalUserAgent:externalUserAgent callback:callback]; } else { if (@available(iOS 13, *)) { _currentSession = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:presentingViewController prefersEphemeralSession:prefersEphemeralSession callback:callback]; } else { _currentSession = [OIDAuthState authStateByPresentingAuthorizationRequest:request presentingViewController:presentingViewController callback:callback]; } } } } /* * Refresh a token with provided OIDServiceConfiguration */ - (void)refreshWithConfiguration: (OIDServiceConfiguration *)configuration redirectUrl: (NSString *) redirectUrl clientId: (NSString *) clientId clientSecret: (NSString *) clientSecret refreshToken: (NSString *) refreshToken scopes: (NSArray *) scopes additionalParameters: (NSDictionary *_Nullable) additionalParameters resolve:(RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { OIDTokenRequest *tokenRefreshRequest = [[OIDTokenRequest alloc] initWithConfiguration:configuration grantType:@"refresh_token" authorizationCode:nil redirectURL:[NSURL URLWithString:redirectUrl] clientID:clientId clientSecret:clientSecret scopes:scopes refreshToken:refreshToken codeVerifier:nil additionalParameters:additionalParameters]; [OIDAuthorizationService performTokenRequest:tokenRefreshRequest callback:^(OIDTokenResponse *_Nullable response, NSError *_Nullable error) { if (response) { resolve([self formatResponse:response]); } else { reject([self getErrorCode: error defaultCode:@"token_refresh_failed"], [self getErrorMessage: error], error); } }]; } - (void)endSessionWithConfiguration: (OIDServiceConfiguration *) configuration idTokenHint: (NSString *) idTokenHint postLogoutRedirectURL: (NSString *) postLogoutRedirectURL additionalParameters: (NSDictionary *_Nullable) additionalParameters iosCustomBrowser: (NSString *) iosCustomBrowser prefersEphemeralSession: (BOOL *) prefersEphemeralSession resolve: (RCTPromiseResolveBlock) resolve reject: (RCTPromiseRejectBlock) reject { OIDEndSessionRequest *endSessionRequest = [[OIDEndSessionRequest alloc] initWithConfiguration: configuration idTokenHint: idTokenHint postLogoutRedirectURL: [NSURL URLWithString:postLogoutRedirectURL] additionalParameters: additionalParameters]; id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager> appDelegate = (id<UIApplicationDelegate, RNAppAuthAuthorizationFlowManager>)[UIApplication sharedApplication].delegate; if (![[appDelegate class] conformsToProtocol:@protocol(RNAppAuthAuthorizationFlowManager)]) { [NSException raise:@"RNAppAuth Missing protocol conformance" format:@"%@ does not conform to RNAppAuthAuthorizationFlowManager", appDelegate]; } appDelegate.authorizationFlowManagerDelegate = self; __weak typeof(self) weakSelf = self; rnAppAuthTaskId = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{ [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; }]; UIViewController *presentingViewController = appDelegate.window.rootViewController.view.window ? appDelegate.window.rootViewController : appDelegate.window.rootViewController.presentedViewController; #if TARGET_OS_MACCATALYST id<OIDExternalUserAgent> externalUserAgent = nil; #elif TARGET_OS_IOS id<OIDExternalUserAgent> externalUserAgent = iosCustomBrowser != nil ? [self getCustomBrowser: iosCustomBrowser] : [self getExternalUserAgentWithPresentingViewController:presentingViewController prefersEphemeralSession:prefersEphemeralSession]; #endif _currentSession = [OIDAuthorizationService presentEndSessionRequest: endSessionRequest externalUserAgent: externalUserAgent callback: ^(OIDEndSessionResponse *_Nullable response, NSError *_Nullable error) { typeof(self) strongSelf = weakSelf; strongSelf->_currentSession = nil; [UIApplication.sharedApplication endBackgroundTask:rnAppAuthTaskId]; rnAppAuthTaskId = UIBackgroundTaskInvalid; if (response) { resolve([self formatEndSessionResponse:response]); } else { reject([self getErrorCode: error defaultCode:@"end_session_failed"], [self getErrorMessage: error], error); } }]; } - (void)configureUrlSession: (NSDictionary*) headers sessionTimeout: (double) sessionTimeout{ NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; if (headers != nil) { configuration.HTTPAdditionalHeaders = headers; } configuration.timeoutIntervalForRequest = sessionTimeout; NSURLSession* session = [NSURLSession sessionWithConfiguration:configuration]; [OIDURLSessionProvider setSession:session]; } /* * Take raw OIDAuthorizationResponse and turn it to response format to pass to JavaScript caller */ - (NSDictionary *)formatAuthorizationResponse: (OIDAuthorizationResponse *) response withCodeVerifier: (NSString *) codeVerifier { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; if (codeVerifier == nil) { return @{@"authorizationCode": response.authorizationCode ? response.authorizationCode : @"", @"state": response.state ? response.state : @"", @"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"tokenType": response.tokenType ? response.tokenType : @"", @"idToken": response.idToken ? response.idToken : @"", @"scopes": response.scope ? [response.scope componentsSeparatedByString:@" "] : [NSArray new], @"additionalParameters": response.additionalParameters, }; } else { return @{@"authorizationCode": response.authorizationCode ? response.authorizationCode : @"", @"state": response.state ? response.state : @"", @"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"tokenType": response.tokenType ? response.tokenType : @"", @"idToken": response.idToken ? response.idToken : @"", @"scopes": response.scope ? [response.scope componentsSeparatedByString:@" "] : [NSArray new], @"additionalParameters": response.additionalParameters, @"codeVerifier": codeVerifier }; } } /* * Take raw OIDTokenResponse and turn it to a token response format to pass to JavaScript caller */ - (NSDictionary*)formatResponse: (OIDTokenResponse*) response { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return @{@"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"additionalParameters": response.additionalParameters, @"idToken": response.idToken ? response.idToken : @"", @"refreshToken": response.refreshToken ? response.refreshToken : @"", @"tokenType": response.tokenType ? response.tokenType : @"", }; } /* * Take raw OIDTokenResponse and additional paramaeters from an OIDAuthorizationResponse * and turn them into an extended token response format to pass to JavaScript caller */ - (NSDictionary*)formatResponse: (OIDTokenResponse*) response withAuthResponse:(OIDAuthorizationResponse*) authResponse { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return @{@"accessToken": response.accessToken ? response.accessToken : @"", @"accessTokenExpirationDate": response.accessTokenExpirationDate ? [dateFormat stringFromDate:response.accessTokenExpirationDate] : @"", @"authorizeAdditionalParameters": authResponse.additionalParameters, @"tokenAdditionalParameters": response.additionalParameters, @"idToken": response.idToken ? response.idToken : @"", @"refreshToken": response.refreshToken ? response.refreshToken : @"", @"tokenType": response.tokenType ? response.tokenType : @"", @"scopes": authResponse.scope ? [authResponse.scope componentsSeparatedByString:@" "] : [NSArray new], }; } - (NSDictionary*)formatRegistrationResponse: (OIDRegistrationResponse*) response { NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; dateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"]; [dateFormat setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"]; return @{@"clientId": response.clientID, @"additionalParameters": response.additionalParameters, @"clientIdIssuedAt": response.clientIDIssuedAt ? [dateFormat stringFromDate:response.clientIDIssuedAt] : @"", @"clientSecret": response.clientSecret ? response.clientSecret : @"", @"clientSecretExpiresAt": response.clientSecretExpiresAt ? [dateFormat stringFromDate:response.clientSecretExpiresAt] : @"", @"registrationAccessToken": response.registrationAccessToken ? response.registrationAccessToken : @"", @"registrationClientUri": response.registrationClientURI ? response.registrationClientURI : @"", @"tokenEndpointAuthMethod": response.tokenEndpointAuthenticationMethod ? response.tokenEndpointAuthenticationMethod : @"", }; } - (NSDictionary*)formatEndSessionResponse: (OIDEndSessionResponse*)response { return @{@"state": response.state ? response.state : @"", @"idTokenHint": response.request.idTokenHint, @"postLogoutRedirectUri": response.request.postLogoutRedirectURL.absoluteString }; } - (NSString*)getErrorCode: (NSError*) error defaultCode: (NSString *) defaultCode { if ([[error domain] isEqualToString:OIDOAuthAuthorizationErrorDomain]) { switch ([error code]) { case OIDErrorCodeOAuthAuthorizationInvalidRequest: return @"invalid_request"; case OIDErrorCodeOAuthAuthorizationUnauthorizedClient: return @"unauthorized_client"; case OIDErrorCodeOAuthAuthorizationAccessDenied: return @"access_denied"; case OIDErrorCodeOAuthAuthorizationUnsupportedResponseType: return @"unsupported_response_type"; case OIDErrorCodeOAuthAuthorizationAuthorizationInvalidScope: return @"invalid_scope"; case OIDErrorCodeOAuthAuthorizationServerError: return @"server_error"; case OIDErrorCodeOAuthAuthorizationTemporarilyUnavailable: return @"temporarily_unavailable"; } } else if ([[error domain] isEqualToString:OIDOAuthTokenErrorDomain]) { switch ([error code]) { case OIDErrorCodeOAuthTokenInvalidRequest: return @"invalid_request"; case OIDErrorCodeOAuthTokenInvalidClient: return @"invalid_client"; case OIDErrorCodeOAuthTokenInvalidGrant: return @"invalid_grant"; case OIDErrorCodeOAuthTokenUnauthorizedClient: return @"unauthorized_client"; case OIDErrorCodeOAuthTokenUnsupportedGrantType: return @"unsupported_grant_type"; case OIDErrorCodeOAuthTokenInvalidScope: return @"invalid_scope"; } } else if ([[error domain] isEqualToString:OIDOAuthRegistrationErrorDomain]) { switch ([error code]) { case OIDErrorCodeOAuthRegistrationInvalidRequest: return @"invalid_request"; case OIDErrorCodeOAuthRegistrationInvalidRedirectURI: return @"invalid_redirect_uri"; case OIDErrorCodeOAuthRegistrationInvalidClientMetadata: return @"invalid_client_metadata"; } } return defaultCode; } #if !TARGET_OS_MACCATALYST - (id<OIDExternalUserAgent>)getCustomBrowser: (NSString *) browserType { typedef id<OIDExternalUserAgent> (^BrowserBlock)(void); NSDictionary *browsers = @{ @"safari": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserSafari]; }, @"chrome": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserChrome]; }, @"opera": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserOpera]; }, @"firefox": ^{ return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserFirefox]; } }; BrowserBlock browser = browsers[browserType]; return browser(); } #endif - (NSString*)getErrorMessage: (NSError*) error { NSDictionary * userInfo = [error userInfo]; if (userInfo && userInfo[OIDOAuthErrorResponseErrorKey] && userInfo[OIDOAuthErrorResponseErrorKey][OIDOAuthErrorFieldErrorDescription]) { return userInfo[OIDOAuthErrorResponseErrorKey][OIDOAuthErrorFieldErrorDescription]; } else { return [error localizedDescription]; } } - (id<OIDExternalUserAgent>)getExternalUserAgentWithPresentingViewController: (UIViewController *)presentingViewController prefersEphemeralSession: (BOOL *) prefersEphemeralSession { id<OIDExternalUserAgent> externalUserAgent; #if TARGET_OS_MACCATALYST externalUserAgent = [[OIDExternalUserAgentCatalyst alloc] initWithPresentingViewController:presentingViewController]; #elif TARGET_OS_IOS if (@available(iOS 13, *)) { externalUserAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController: presentingViewController prefersEphemeralSession:prefersEphemeralSession]; } else { externalUserAgent = [[OIDExternalUserAgentIOS alloc] initWithPresentingViewController: presentingViewController]; } #elif TARGET_OS_OSX externalUserAgent = [[OIDExternalUserAgentMac alloc] init]; #endif return externalUserAgent; } @end
Encontrar la diferencia