diff --git a/Example/ViewController.swift b/Example/ViewController.swift index f38fff96d9c..dfd32b8f6b8 100644 --- a/Example/ViewController.swift +++ b/Example/ViewController.swift @@ -52,9 +52,11 @@ final class ViewController: UIViewController { let configuration = try? OktaOidcConfig.default() configuration?.requestCustomizationDelegate = self + + configuration?.tokenValidator = self + oktaAppAuth = try? OktaOidc(configuration: isUITest ? testConfig : configuration) AppDelegate.shared.oktaOidc = oktaAppAuth - if let config = oktaAppAuth?.configuration { authStateManager = OktaOidcStateManager.readFromSecureStorage(for: config) authStateManager?.requestCustomizationDelegate = self @@ -117,21 +119,43 @@ final class ViewController: UIViewController { @IBAction func introspectButton(_ sender: Any) { // Get current accessToken - guard let accessToken = authStateManager?.accessToken else { return } - - authStateManager?.introspect(token: accessToken, callback: { payload, error in - guard let isValid = payload?["active"] as? Bool else { - self.showMessage("Error: \(error?.localizedDescription ?? "Unknown")") - return + var accessToken = authStateManager?.accessToken + if accessToken == nil { + authStateManager?.renew { newAuthStateManager, error in + if let error = error { + // Error + print("Error trying to Refresh AccessToken: \(error)") + return + } + self.authStateManager = newAuthStateManager + accessToken = newAuthStateManager?.accessToken + + self.authStateManager?.introspect(token: accessToken, callback: { payload, error in + guard let isValid = payload?["active"] as? Bool else { + self.showMessage("Error: \(error?.localizedDescription ?? "Unknown")") + return + } + + self.showMessage("Is the AccessToken valid? - \(isValid)") + }) } - - self.showMessage("Is the AccessToken valid? - \(isValid)") - }) + } else { + authStateManager?.introspect(token: accessToken, callback: { payload, error in + guard let isValid = payload?["active"] as? Bool else { + self.showMessage("Error: \(error?.localizedDescription ?? "Unknown")") + return + } + + self.showMessage("Is the AccessToken valid? - \(isValid)") + }) + } } @IBAction func revokeButton(_ sender: Any) { // Get current accessToken - guard let accessToken = authStateManager?.accessToken else { return } + guard let accessToken = authStateManager?.accessToken else { + return + } authStateManager?.revoke(accessToken) { _, error in if error != nil { self.showMessage("Error: \(error!)") } @@ -224,6 +248,28 @@ extension ViewController: OktaNetworkRequestCustomizationDelegate { } } +extension ViewController: OKTTokenValidator { + func isIssued(atDateValid issuedAt: Date?, token: OKTTokenType) -> Bool { + guard let issuedAt = issuedAt else { + return false + } + + let now = Date() + + return fabs(now.timeIntervalSince(issuedAt)) <= 200 + } + + func isDateExpired(_ expiry: Date?, token tokenType: OKTTokenType) -> Bool { + guard let expiry = expiry else { + return false + } + + let now = Date() + + return now >= expiry + } +} + extension OktaOidcError { var displayMessage: String { switch self { diff --git a/README.md b/README.md index bbce9f5f43b..9dbffa04158 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,17 @@ if #available(iOS 13.0, *) { ``` ***Note*** Flag is available on iOS 13 and above versions + +### Token Time Validation + +Custom token time validation is possible by adopting to `OKTTokenValidator` protocol and then setting `tokenValidator` variable: + +```swift +configuration?.tokenValidator = self +``` + +By default `OKTDefaultTokenValidator` object is set. + ### How to use in Objective-C project To use this SDK in Objective-C project, you should do the following: diff --git a/Sources/AppAuth/OKTAuthState.m b/Sources/AppAuth/OKTAuthState.m index bef88a498d7..58bc100d850 100644 --- a/Sources/AppAuth/OKTAuthState.m +++ b/Sources/AppAuth/OKTAuthState.m @@ -32,6 +32,7 @@ #import "OKTTokenRequest.h" #import "OKTTokenResponse.h" #import "OKTTokenUtilities.h" +#import "OKTDefaultTokenValidator.h" /*! @brief Key used to encode the @c refreshToken property for @c NSSecureCoding. */ @@ -131,6 +132,7 @@ @implementation OKTAuthState { authStateByPresentingAuthorizationRequest:(OKTAuthorizationRequest *)authorizationRequest externalUserAgent:(id)externalUserAgent delegate:(id _Nullable)delegate + validator:(id _Nonnull)validator callback:(OKTAuthStateAuthorizationCallback)callback { // presents the authorization request id authFlowSession = [OKTAuthorizationService @@ -151,6 +153,7 @@ @implementation OKTAuthState { [OKTAuthorizationService performTokenRequest:tokenExchangeRequest originalAuthorizationResponse:authorizationResponse delegate:delegate + validator:validator callback:^(OKTTokenResponse * _Nullable tokenResponse, NSError * _Nullable tokenError) { OKTAuthState *authState; if (tokenResponse) { @@ -199,7 +202,11 @@ - (instancetype)initWithAuthorizationResponse:(OKTAuthorizationResponse *)author */ - (instancetype)initWithAuthorizationResponse:(OKTAuthorizationResponse *)authorizationResponse tokenResponse:(nullable OKTTokenResponse *)tokenResponse { - return [self initWithAuthorizationResponse:authorizationResponse tokenResponse:tokenResponse registrationResponse:nil delegate:nil]; + return [self initWithAuthorizationResponse:authorizationResponse + tokenResponse:tokenResponse + registrationResponse:nil + delegate:nil + validator:[OKTDefaultTokenValidator new]]; } /*! @brief Creates an auth state from an registration response. @@ -209,17 +216,20 @@ - (instancetype)initWithRegistrationResponse:(OKTRegistrationResponse *)registra return [self initWithAuthorizationResponse:nil tokenResponse:nil registrationResponse:registrationResponse - delegate:nil]; + delegate:nil + validator:[OKTDefaultTokenValidator new]]; } - (instancetype)initWithAuthorizationResponse: (nullable OKTAuthorizationResponse *)authorizationResponse tokenResponse:(nullable OKTTokenResponse *)tokenResponse registrationResponse:(nullable OKTRegistrationResponse *)registrationResponse - delegate:(nullable id)delegate { + delegate:(nullable id)delegate + validator:(nonnull id)validator { self = [super init]; if (self) { _delegate = delegate; + _validator = validator; _pendingActionsSyncObject = [[NSObject alloc] init]; if (registrationResponse) { @@ -510,13 +520,14 @@ - (void)performActionWithFreshTokens:(OKTAuthStateAction)action // creates a list of pending actions, starting with this one _pendingActions = [NSMutableArray arrayWithObject:pendingAction]; } - + // refresh the tokens OKTTokenRequest *tokenRefreshRequest = [self tokenRefreshRequestWithAdditionalParameters:additionalParameters]; [OKTAuthorizationService performTokenRequest:tokenRefreshRequest originalAuthorizationResponse:_lastAuthorizationResponse delegate:_delegate + validator:_validator callback:^(OKTTokenResponse *_Nullable response, NSError *_Nullable error) { // update OKTAuthState based on response diff --git a/Sources/AppAuth/OKTAuthorizationService.m b/Sources/AppAuth/OKTAuthorizationService.m index 5fa5f4d7aa3..37021c19fe0 100644 --- a/Sources/AppAuth/OKTAuthorizationService.m +++ b/Sources/AppAuth/OKTAuthorizationService.m @@ -37,17 +37,13 @@ #import "OKTTokenResponse.h" #import "OKTURLQueryComponent.h" #import "OKTURLSessionProvider.h" +#import "OKTDefaultTokenValidator.h" /*! @brief Path appended to an OpenID Connect issuer for discovery @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig */ static NSString *const kOpenIDConfigurationWellKnownPath = @".well-known/openid-configuration"; -/*! @brief Max allowable iat (Issued At) time skew - @see https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation - */ -static int const kOKTAuthorizationSessionIATMaxSkew = 600; - NS_ASSUME_NONNULL_BEGIN @interface OKTAuthorizationSession : NSObject @@ -425,12 +421,17 @@ + (void)discoverServiceConfigurationForDiscoveryURL:(NSURL *)discoveryURL + (void)performTokenRequest:(OKTTokenRequest *)request delegate:(id _Nullable)delegate callback:(OKTTokenCallback)callback { - [[self class] performTokenRequest:request originalAuthorizationResponse:nil delegate:delegate callback:callback]; + [[self class] performTokenRequest:request + originalAuthorizationResponse:nil + delegate:delegate + validator:[[OKTDefaultTokenValidator alloc] init] + callback:callback]; } + (void)performTokenRequest:(OKTTokenRequest *)request originalAuthorizationResponse:(OKTAuthorizationResponse *_Nullable)authorizationResponse delegate:(id _Nullable)delegate + validator:(id _Nonnull)validator callback:(OKTTokenCallback)callback { NSURLRequest *URLRequest = [request URLRequest]; @@ -607,37 +608,32 @@ + (void)performTokenRequest:(OKTTokenRequest *)request // OpenID Connect Core Section 3.1.3.7. rules #7 & #8 // Not applicable. See rule #6. + + NSAssert(validator != nil, @"Validator parameter is missed. Default will be used."); + id tokenValidator = validator ?: [OKTDefaultTokenValidator new]; - // OpenID Connect Core Section 3.1.3.7. rule #9 - // Validates that the current time is before the expiry time. - NSTimeInterval expiresAtDifference = [idToken.expiresAt timeIntervalSinceNow]; - if (expiresAtDifference < 0) { + if ([tokenValidator isDateExpired:idToken.expiresAt token:OKTTokenTypeId]) { NSError *invalidIDToken = - [OKTErrorUtilities errorWithCode:OKTErrorCodeIDTokenFailedValidationError - underlyingError:nil - description:@"ID Token expired"]; + [OKTErrorUtilities errorWithCode:OKTErrorCodeIDTokenFailedValidationError + underlyingError:nil + description:@"ID Token expired"]; dispatch_async(dispatch_get_main_queue(), ^{ callback(nil, invalidIDToken); }); return; } - - // OpenID Connect Core Section 3.1.3.7. rule #10 - // Validates that the issued at time is not more than +/- 10 minutes on the current time. - NSTimeInterval issuedAtDifference = [idToken.issuedAt timeIntervalSinceNow]; - if (fabs(issuedAtDifference) > kOKTAuthorizationSessionIATMaxSkew) { - NSString *message = - [NSString stringWithFormat:@"Issued at time is more than %d seconds before or after " - "the current time", - kOKTAuthorizationSessionIATMaxSkew]; - NSError *invalidIDToken = + + if (![tokenValidator isIssuedAtDateValid:idToken.issuedAt token:OKTTokenTypeId]) { + NSString *message = + [NSString stringWithFormat:@"Issued at time is invalid corresponding to the current time"]; + NSError *invalidIDToken = [OKTErrorUtilities errorWithCode:OKTErrorCodeIDTokenFailedValidationError underlyingError:nil description:message]; - dispatch_async(dispatch_get_main_queue(), ^{ - callback(nil, invalidIDToken); - }); - return; + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, invalidIDToken); + }); + return; } // Only relevant for the authorization_code response type diff --git a/Sources/AppAuth/OKTDefaultTokenValidator.m b/Sources/AppAuth/OKTDefaultTokenValidator.m new file mode 100644 index 00000000000..35208602d1d --- /dev/null +++ b/Sources/AppAuth/OKTDefaultTokenValidator.m @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +#import "OKTDefaultTokenValidator.h" + +int const kOKTAuthorizationSessionIATMaxSkew = 600; + +@implementation OKTDefaultTokenValidator + +- (BOOL)isDateExpired:(nullable NSDate *)expiresAtDate token:(OKTTokenType)tokenType { + if (!expiresAtDate) { + return YES; + } + + switch (tokenType) { + case OKTTokenTypeId: { + // OpenID Connect Core Section 3.1.3.7. rule #9 + // Validates that the current time is before the expiry time. + NSTimeInterval expiresAtDifference = [expiresAtDate timeIntervalSinceNow]; + return expiresAtDifference < 0; + } + case OKTTokenTypeAccess: + return expiresAtDate.timeIntervalSince1970 <= [NSDate new].timeIntervalSince1970; + default: + NSAssert(NO, @"Unknown token type."); + return YES; + } +} + +- (BOOL)isIssuedAtDateValid:(nullable NSDate *)issuedAt token:(OKTTokenType)tokenType { + if (!issuedAt) { + return NO; + } + + // OpenID Connect Core Section 3.1.3.7. rule #10 + // Validates that the issued at time is not more than +/- 10 minutes on the current time. + NSTimeInterval issuedAtDifference = [issuedAt timeIntervalSinceNow]; + return fabs(issuedAtDifference) <= kOKTAuthorizationSessionIATMaxSkew; +} + +@end diff --git a/Sources/AppAuth/iOS/OKTAuthState+IOS.m b/Sources/AppAuth/iOS/OKTAuthState+IOS.m index 0559b244ea6..d910cc3f8b2 100644 --- a/Sources/AppAuth/iOS/OKTAuthState+IOS.m +++ b/Sources/AppAuth/iOS/OKTAuthState+IOS.m @@ -32,6 +32,7 @@ @implementation OKTAuthState (IOS) authStateByPresentingAuthorizationRequest:(OKTAuthorizationRequest *)authorizationRequest presentingViewController:(UIViewController *)presentingViewController delegate:(id _Nullable)delegate + validator:(id _Nullable)validator callback:(OKTAuthStateAuthorizationCallback)callback { OKTExternalUserAgentIOS *externalUserAgent = [[OKTExternalUserAgentIOS alloc] @@ -39,17 +40,20 @@ @implementation OKTAuthState (IOS) return [self authStateByPresentingAuthorizationRequest:authorizationRequest externalUserAgent:externalUserAgent delegate:delegate + validator: validator callback:callback]; } + (id) authStateByPresentingAuthorizationRequest:(OKTAuthorizationRequest *)authorizationRequest delegate:(id _Nullable)delegate + validator:(id _Nullable)validator callback:(OKTAuthStateAuthorizationCallback)callback { OKTExternalUserAgentIOS *externalUserAgent = [[OKTExternalUserAgentIOS alloc] init]; return [self authStateByPresentingAuthorizationRequest:authorizationRequest externalUserAgent:externalUserAgent delegate:delegate + validator: validator callback:callback]; } diff --git a/Sources/AppAuth/include/AppAuthCore.h b/Sources/AppAuth/include/AppAuthCore.h index 4e3c8d3ab61..38e61d4bc61 100644 --- a/Sources/AppAuth/include/AppAuthCore.h +++ b/Sources/AppAuth/include/AppAuthCore.h @@ -44,3 +44,4 @@ #import "OKTURLSessionProvider.h" #import "OKTEndSessionRequest.h" #import "OKTEndSessionResponse.h" +#import "OKTDefaultTokenValidator.h" diff --git a/Sources/AppAuth/include/OKTAuthState+IOS.h b/Sources/AppAuth/include/OKTAuthState+IOS.h index d98eaa6a764..51b4e72dda0 100644 --- a/Sources/AppAuth/include/OKTAuthState+IOS.h +++ b/Sources/AppAuth/include/OKTAuthState+IOS.h @@ -52,11 +52,13 @@ NS_ASSUME_NONNULL_BEGIN authStateByPresentingAuthorizationRequest:(OKTAuthorizationRequest *)authorizationRequest presentingViewController:(UIViewController *)presentingViewController delegate:(id _Nullable)delegate + validator:(id _Nullable)validator callback:(OKTAuthStateAuthorizationCallback)callback; + (id) authStateByPresentingAuthorizationRequest:(OKTAuthorizationRequest *)authorizationRequest delegate:(id _Nullable)delegate + validator:(id _Nullable)validator callback:(OKTAuthStateAuthorizationCallback)callback API_AVAILABLE(ios(11)) __deprecated_msg("This method will not work on iOS 13. Use " "authStateByPresentingAuthorizationRequest:presentingViewController:callback:"); diff --git a/Sources/AppAuth/include/OKTAuthState.h b/Sources/AppAuth/include/OKTAuthState.h index 35ae658cf79..852c3acf17c 100644 --- a/Sources/AppAuth/include/OKTAuthState.h +++ b/Sources/AppAuth/include/OKTAuthState.h @@ -30,6 +30,7 @@ @protocol OKTExternalUserAgent; @protocol OKTExternalUserAgentSession; @protocol OktaNetworkRequestCustomizationDelegate; +@protocol OKTTokenValidator; NS_ASSUME_NONNULL_BEGIN @@ -112,6 +113,11 @@ typedef void (^OKTAuthStateAuthorizationCallback)(OKTAuthState *_Nullable authSt */ @property(nonatomic, weak, nullable)id delegate; +/*! @brief The @c OKTTokenValidator validator. + @discussion Use a custom validator to verify issuedAt/expired time of tokens. + */ +@property(nonatomic, strong, nonnull) id validator; + /*! @brief The @c OKTAuthStateChangeDelegate delegate. @discussion Use the delegate to observe state changes (and update storage) as well as error states. @@ -142,6 +148,7 @@ typedef void (^OKTAuthStateAuthorizationCallback)(OKTAuthState *_Nullable authSt authStateByPresentingAuthorizationRequest:(OKTAuthorizationRequest *)authorizationRequest externalUserAgent:(id)externalUserAgent delegate:(id _Nullable)delegate + validator:(id _Nonnull)validator callback:(OKTAuthStateAuthorizationCallback)callback; /*! @internal @@ -177,6 +184,7 @@ typedef void (^OKTAuthStateAuthorizationCallback)(OKTAuthState *_Nullable authSt tokenResponse:(nullable OKTTokenResponse *)tokenResponse registrationResponse:(nullable OKTRegistrationResponse *)registrationResponse delegate:(nullable id)delegate + validator:(nonnull id)validator NS_DESIGNATED_INITIALIZER; /*! @brief Updates the authorization state based on a new authorization response. diff --git a/Sources/AppAuth/include/OKTAuthorizationService.h b/Sources/AppAuth/include/OKTAuthorizationService.h index 6f00e9fbb64..1988e928955 100644 --- a/Sources/AppAuth/include/OKTAuthorizationService.h +++ b/Sources/AppAuth/include/OKTAuthorizationService.h @@ -20,6 +20,7 @@ #import #import "OktaNetworkRequestCustomizationDelegate.h" +#import "OKTTokenValidator.h" @class OKTAuthorization; @class OKTAuthorizationRequest; @@ -159,11 +160,13 @@ typedef void (^OKTRegistrationCompletion)(OKTRegistrationResponse *_Nullable reg @param request The token request. @param authorizationResponse The original authorization response related to this token request. @param delegate The network request customization delegate. + @param validator Validates token. @param callback The method called when the request has completed or failed. */ + (void)performTokenRequest:(OKTTokenRequest *)request originalAuthorizationResponse:(OKTAuthorizationResponse *_Nullable)authorizationResponse delegate:(id _Nullable)delegate + validator:(id _Nonnull)validator callback:(OKTTokenCallback)callback; /*! @brief Performs a registration request. diff --git a/Sources/AppAuth/include/OKTDefaultTokenValidator.h b/Sources/AppAuth/include/OKTDefaultTokenValidator.h new file mode 100644 index 00000000000..23e6f35d973 --- /dev/null +++ b/Sources/AppAuth/include/OKTDefaultTokenValidator.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +#import +#import "OKTTokenValidator.h" + +/*! @brief Max allowable iat (Issued At) time skew + @see https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation + */ +extern int const kOKTAuthorizationSessionIATMaxSkew; + +@interface OKTDefaultTokenValidator : NSObject + +@end diff --git a/Sources/AppAuth/include/OKTTokenValidator.h b/Sources/AppAuth/include/OKTTokenValidator.h new file mode 100644 index 00000000000..6cbb50821a5 --- /dev/null +++ b/Sources/AppAuth/include/OKTTokenValidator.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + + +#import + +typedef NS_ENUM(NSInteger, OKTTokenType) { + OKTTokenTypeId, + OKTTokenTypeAccess, +}; + +/*! @brief Allows to custom logic/time source to verify a tokens issueAt/expiry time. + @discussion More information could be found here: https://github.com/okta/okta-oidc-ios/blob/master/README.md#TODO. + */ +@protocol OKTTokenValidator + +/*! @brief Check issuedAt time using custom logic/time source. + @param issuedAt Tokens issuedAt Date. + @return bool of result. +*/ +- (BOOL)isIssuedAtDateValid:(nullable NSDate *)issuedAt token:(OKTTokenType)tokenType; + +/*! @brief Check expiry time using custom logic/time source. + @param expiry Tokens expiry Date. +*/ +- (BOOL)isDateExpired:(nullable NSDate *)expiry token:(OKTTokenType)tokenType; + +@end diff --git a/Sources/AppAuth/macOS/OKTAuthState+Mac.m b/Sources/AppAuth/macOS/OKTAuthState+Mac.m index c9b69a2012e..a2a01a38f01 100644 --- a/Sources/AppAuth/macOS/OKTAuthState+Mac.m +++ b/Sources/AppAuth/macOS/OKTAuthState+Mac.m @@ -22,6 +22,7 @@ #if TARGET_OS_OSX +#import "OKTDefaultTokenValidator.h" #import "OKTAuthState+Mac.h" #import "OKTExternalUserAgentMac.h" @@ -35,6 +36,7 @@ @implementation OKTAuthState (Mac) return [self authStateByPresentingAuthorizationRequest:authorizationRequest externalUserAgent:externalUserAgent delegate:nil + validator:[OKTDefaultTokenValidator new] callback:callback]; } diff --git a/Sources/OktaOidc/Common/Internal/OIDAuthState+Okta.swift b/Sources/OktaOidc/Common/Internal/OIDAuthState+Okta.swift index 3dbe269c942..fda1f3cc2b9 100644 --- a/Sources/OktaOidc/Common/Internal/OIDAuthState+Okta.swift +++ b/Sources/OktaOidc/Common/Internal/OIDAuthState+Okta.swift @@ -17,7 +17,7 @@ import OktaOidc_AppAuth // Okta Extension of OIDAuthState extension OKTAuthState { - static func getState(withAuthRequest authRequest: OKTAuthorizationRequest, delegate: OktaNetworkRequestCustomizationDelegate? = nil, callback finalize: @escaping (OKTAuthState?, OktaOidcError?) -> Void ) { + static func getState(withAuthRequest authRequest: OKTAuthorizationRequest, delegate: OktaNetworkRequestCustomizationDelegate? = nil, validator: OKTTokenValidator, callback finalize: @escaping (OKTAuthState?, OktaOidcError?) -> Void ) { // Make authCode request OKTAuthorizationService.perform(authRequest: authRequest, delegate: delegate) { authResponse, error in @@ -39,7 +39,10 @@ extension OKTAuthState { } // Make token request - OKTAuthorizationService.perform(tokenRequest, originalAuthorizationResponse: authResponse, delegate: delegate) { tokenResponse, error in + OKTAuthorizationService.perform(tokenRequest, + originalAuthorizationResponse: authResponse, + delegate: delegate, + validator: validator) { tokenResponse, error in guard let tokenResponse = tokenResponse else { finalize(nil, OktaOidcError.api(message: "Authorization Error: \(error?.localizedDescription ?? "No token response.")", underlyingError: error)) return @@ -54,7 +57,8 @@ extension OKTAuthState { let authState = OKTAuthState(authorizationResponse: authResponse, tokenResponse: tokenResponse, registrationResponse: nil, - delegate: delegate) + delegate: delegate, + validator: validator) finalize(authState, nil) } } diff --git a/Sources/OktaOidc/Common/Internal/OktaOidcRestApi.swift b/Sources/OktaOidc/Common/Internal/OktaOidcRestApi.swift index 90eb512ab57..717eb3e9222 100644 --- a/Sources/OktaOidc/Common/Internal/OktaOidcRestApi.swift +++ b/Sources/OktaOidc/Common/Internal/OktaOidcRestApi.swift @@ -16,7 +16,7 @@ import OktaOidc_AppAuth class OktaOidcRestApi: OktaOidcHttpApiProtocol { weak var requestCustomizationDelegate: OktaNetworkRequestCustomizationDelegate? - + func fireRequest(_ request: URLRequest, onSuccess: @escaping OktaApiSuccessCallback, onError: @escaping OktaApiErrorCallback) { diff --git a/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcAuthenticate.swift b/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcAuthenticate.swift index 041ed5aca10..2719b727d5f 100644 --- a/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcAuthenticate.swift +++ b/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcAuthenticate.swift @@ -20,6 +20,7 @@ class OktaOidcAuthenticateTask: OktaOidcTask { func authenticateWithSessionToken(sessionToken: String, delegate: OktaNetworkRequestCustomizationDelegate? = nil, + validator: OKTTokenValidator, callback: @escaping (OKTAuthState?, OktaOidcError?) -> Void) { self.downloadOidcConfiguration() { oidConfig, error in guard let oidConfig = oidConfig else { @@ -48,7 +49,7 @@ class OktaOidcAuthenticateTask: OktaOidcTask { additionalParameters: additionalParameters ) - OKTAuthState.getState(withAuthRequest: request, delegate: delegate, callback: { authState, error in + OKTAuthState.getState(withAuthRequest: request, delegate: delegate, validator: validator, callback: { authState, error in callback(authState, error) }) } diff --git a/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcBrowserTask.swift b/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcBrowserTask.swift index d131a9b0703..abc1e9ec257 100644 --- a/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcBrowserTask.swift +++ b/Sources/OktaOidc/Common/Internal/Tasks/OktaOidcBrowserTask.swift @@ -21,6 +21,7 @@ class OktaOidcBrowserTask: OktaOidcTask { var userAgentSession: OKTExternalUserAgentSession? func signIn(delegate: OktaNetworkRequestCustomizationDelegate? = nil, + validator: OKTTokenValidator, callback: @escaping ((OKTAuthState?, OktaOidcError?) -> Void)) { self.downloadOidcConfiguration() { oidConfig, error in guard let oidConfiguration = oidConfig else { @@ -46,7 +47,8 @@ class OktaOidcBrowserTask: OktaOidcTask { let userAgentSession = self.authStateClass().authState(byPresenting: request, externalUserAgent: externalUserAgent, - delegate: delegate) { authorizationResponse, error in + delegate: delegate, + validator: validator) { authorizationResponse, error in defer { self.userAgentSession = nil } if let authResponse = authorizationResponse { diff --git a/Sources/OktaOidc/Common/OktaOidc.swift b/Sources/OktaOidc/Common/OktaOidc.swift index 9b9d015db87..40a940201fe 100644 --- a/Sources/OktaOidc/Common/OktaOidc.swift +++ b/Sources/OktaOidc/Common/OktaOidc.swift @@ -38,6 +38,7 @@ public class OktaOidc: NSObject { task.authenticateWithSessionToken( sessionToken: sessionToken, delegate: configuration.requestCustomizationDelegate, + validator: configuration.tokenValidator, callback: { (authState, error) in guard let authState = authState else { callback(nil, error) @@ -60,7 +61,8 @@ public class OktaOidc: NSObject { callback: @escaping ((OktaOidcStateManager?, Error?) -> Void)) { currentUserSessionTask = task - task.signIn(delegate: configuration.requestCustomizationDelegate) { [weak self] authState, error in + task.signIn(delegate: configuration.requestCustomizationDelegate, + validator: configuration.tokenValidator) { [weak self] authState, error in defer { self?.currentUserSessionTask = nil } guard let authState = authState else { callback(nil, error) @@ -71,6 +73,9 @@ public class OktaOidc: NSObject { if let delegate = self?.configuration.requestCustomizationDelegate { authStateManager.requestCustomizationDelegate = delegate } + if let validator = self?.configuration.tokenValidator { + authStateManager.tokenValidator = validator + } callback(authStateManager, nil) } } diff --git a/Sources/OktaOidc/Common/OktaOidcConfig.swift b/Sources/OktaOidc/Common/OktaOidcConfig.swift index d409831019e..c3ccc7978c3 100644 --- a/Sources/OktaOidc/Common/OktaOidcConfig.swift +++ b/Sources/OktaOidc/Common/OktaOidcConfig.swift @@ -30,7 +30,9 @@ public class OktaOidcConfig: NSObject { requests throughout OktaOidc. More information could be found here: https://github.com/okta/okta-oidc-ios/blob/master/README.md#modify-network-requests. */ @objc public weak var requestCustomizationDelegate: OktaNetworkRequestCustomizationDelegate? - + + @objc public var tokenValidator: OKTTokenValidator = OKTDefaultTokenValidator() + @available(iOS 13.0, *) @objc public lazy var noSSO = false diff --git a/Sources/OktaOidc/Common/OktaOidcStateManager.swift b/Sources/OktaOidc/Common/OktaOidcStateManager.swift index a5641a3b431..02229b3e620 100644 --- a/Sources/OktaOidc/Common/OktaOidcStateManager.swift +++ b/Sources/OktaOidc/Common/OktaOidcStateManager.swift @@ -32,13 +32,22 @@ open class OktaOidcStateManager: NSObject, NSSecureCoding { authState.delegate = newValue } } + + @objc public var tokenValidator: OKTTokenValidator { + get { + authState.validator + } + set { + authState.validator = newValue + } + } @objc open var accessToken: String? { // Return the known accessToken if it hasn't expired guard let tokenResponse = self.authState.lastTokenResponse, let token = tokenResponse.accessToken, let tokenExp = tokenResponse.accessTokenExpirationDate, - tokenExp.timeIntervalSince1970 > Date().timeIntervalSince1970 else { + !tokenValidator.isDateExpired(tokenExp, token: .access) else { return nil } @@ -93,7 +102,9 @@ open class OktaOidcStateManager: NSObject, NSSecureCoding { return OktaOidcError.JWTDecodeError } - if tokenObject.expiresAt.timeIntervalSinceNow < 0 { + if tokenValidator.isDateExpired(tokenObject.expiresAt, token: .id) { + return OktaOidcError.JWTValidationError("ID Token expired") + } else if tokenObject.expiresAt.timeIntervalSinceNow < 0 { return OktaOidcError.JWTValidationError("ID Token expired") } diff --git a/Sources/OktaOidc/macOS/Internal/Tasks/OktaOidcBrowserTaskMAC.swift b/Sources/OktaOidc/macOS/Internal/Tasks/OktaOidcBrowserTaskMAC.swift index e6f54160a19..9a0a181408d 100644 --- a/Sources/OktaOidc/macOS/Internal/Tasks/OktaOidcBrowserTaskMAC.swift +++ b/Sources/OktaOidc/macOS/Internal/Tasks/OktaOidcBrowserTaskMAC.swift @@ -53,9 +53,9 @@ class OktaOidcBrowserTaskMAC: OktaOidcBrowserTask { didSet { self.redirectServer?.redirectHandler.currentAuthorizationFlow = userAgentSession } - } + } - override func signIn(delegate: OktaNetworkRequestCustomizationDelegate? = nil, callback: @escaping ((OKTAuthState?, OktaOidcError?) -> Void)) { + override func signIn(delegate: OktaNetworkRequestCustomizationDelegate? = nil, validator: OKTTokenValidator, callback: @escaping ((OKTAuthState?, OktaOidcError?) -> Void)) { if let redirectServer = self.redirectServer { do { redirectURL = try redirectServer.startListener(with: domainName) @@ -67,7 +67,7 @@ class OktaOidcBrowserTaskMAC: OktaOidcBrowserTask { redirectURL = self.config.redirectUri } - super.signIn(callback: callback) + super.signIn(validator: config.tokenValidator, callback: callback) } override func signOutWithIdToken(idToken: String, callback: @escaping (Void?, OktaOidcError?) -> Void) { diff --git a/Tests/AppAuthTests/OKTDefaultTokenValidatorTests.h b/Tests/AppAuthTests/OKTDefaultTokenValidatorTests.h new file mode 100644 index 00000000000..187e8cd8090 --- /dev/null +++ b/Tests/AppAuthTests/OKTDefaultTokenValidatorTests.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OKTDefaultTokenValidatorTests : XCTestCase + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/AppAuthTests/OKTDefaultTokenValidatorTests.m b/Tests/AppAuthTests/OKTDefaultTokenValidatorTests.m new file mode 100644 index 00000000000..f63ac2cd53a --- /dev/null +++ b/Tests/AppAuthTests/OKTDefaultTokenValidatorTests.m @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022-Present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +#import "OKTDefaultTokenValidatorTests.h" +#import "OKTDefaultTokenValidator.h" + +@implementation OKTDefaultTokenValidatorTests + +- (void)testDateExpiredValidationIDToken { + id validator = [OKTDefaultTokenValidator new]; + + // Future + XCTAssertFalse([validator isDateExpired:[NSDate dateWithTimeIntervalSinceNow:100] token:OKTTokenTypeId]); + // Past + XCTAssertTrue([validator isDateExpired:[NSDate dateWithTimeIntervalSinceNow:-100] token:OKTTokenTypeId]); + // nil + XCTAssertTrue([validator isDateExpired:nil token:OKTTokenTypeId]); +} + +- (void)testIssuedAtValidationIDToken { + id validator = [OKTDefaultTokenValidator new]; + + // Past + XCTAssertTrue([validator isIssuedAtDateValid:[NSDate dateWithTimeIntervalSinceNow:-100] token:OKTTokenTypeId]); + // Now + XCTAssertTrue([validator isIssuedAtDateValid:[NSDate dateWithTimeIntervalSinceNow:0] token:OKTTokenTypeId]); + // Future + XCTAssertTrue([validator isIssuedAtDateValid:[NSDate dateWithTimeIntervalSinceNow:100] token:OKTTokenTypeId]); + // Max time + XCTAssertFalse([validator isIssuedAtDateValid:[NSDate dateWithTimeIntervalSinceNow:kOKTAuthorizationSessionIATMaxSkew + 1] token:OKTTokenTypeId]); + // nil + XCTAssertFalse([validator isIssuedAtDateValid:nil token:OKTTokenTypeId]); +} + +- (void)testDateExpiredValidationAccessToken { + id validator = [OKTDefaultTokenValidator new]; + + // Future + XCTAssertFalse([validator isDateExpired:[NSDate dateWithTimeIntervalSinceNow:100] token:OKTTokenTypeAccess]); + // Past + XCTAssertTrue([validator isDateExpired:[NSDate dateWithTimeIntervalSinceNow:-100] token:OKTTokenTypeAccess]); + // nil + XCTAssertTrue([validator isDateExpired:nil token:OKTTokenTypeAccess]); +} + +@end diff --git a/Tests/Common/OIDAuthStateMACMock.swift b/Tests/Common/OIDAuthStateMACMock.swift index 58c8a23753e..1e992b5916c 100644 --- a/Tests/Common/OIDAuthStateMACMock.swift +++ b/Tests/Common/OIDAuthStateMACMock.swift @@ -21,6 +21,7 @@ class OKTAuthStateMACMock: OKTAuthState { override class func authState(byPresenting authorizationRequest: OKTAuthorizationRequest, externalUserAgent: OKTExternalUserAgent, delegate: OktaNetworkRequestCustomizationDelegate?, + validator: OKTTokenValidator, callback: @escaping OKTAuthStateAuthorizationCallback) -> OKTExternalUserAgentSession { DispatchQueue.main.async { // http://127.0.0.1:60000/ - is intended for cancellation tests diff --git a/Tests/Common/OKTAuthStateMock.swift b/Tests/Common/OKTAuthStateMock.swift index f5cc529b79b..7fb78411282 100644 --- a/Tests/Common/OKTAuthStateMock.swift +++ b/Tests/Common/OKTAuthStateMock.swift @@ -22,6 +22,7 @@ class OKTAuthStateMock: OKTAuthState { override class func authState(byPresenting authorizationRequest: OKTAuthorizationRequest, externalUserAgent: OKTExternalUserAgent, delegate: OktaNetworkRequestCustomizationDelegate?, + validator: OKTTokenValidator, callback: @escaping OKTAuthStateAuthorizationCallback) -> OKTExternalUserAgentSession { DispatchQueue.main.async { let authState = TestUtils.setupMockAuthState(issuer: TestUtils.mockIssuer, clientId: TestUtils.mockClientId) diff --git a/Tests/Common/OktaOidcBrowserTaskMacMock.swift b/Tests/Common/OktaOidcBrowserTaskMacMock.swift index 817d5ca533a..dac565be0e0 100644 --- a/Tests/Common/OktaOidcBrowserTaskMacMock.swift +++ b/Tests/Common/OktaOidcBrowserTaskMacMock.swift @@ -28,7 +28,7 @@ class OktaOidcBrowserTaskMACUnitMock: OktaOidcBrowserTaskMAC { var signOutCalled = false var error: OktaOidcError? - override func signIn(delegate: OktaNetworkRequestCustomizationDelegate? = nil, callback: @escaping ((OKTAuthState?, OktaOidcError?) -> Void)) { + override func signIn(delegate: OktaNetworkRequestCustomizationDelegate? = nil, validator: OKTTokenValidator, callback: @escaping ((OKTAuthState?, OktaOidcError?) -> Void)) { DispatchQueue.main.async { self.signInCalled = true if let error = self.error { diff --git a/Tests/OktaOidcTests/OktaOIDAuthStateTests.swift b/Tests/OktaOidcTests/OktaOIDAuthStateTests.swift index 17dd7ce40f7..f1403fa147f 100644 --- a/Tests/OktaOidcTests/OktaOIDAuthStateTests.swift +++ b/Tests/OktaOidcTests/OktaOIDAuthStateTests.swift @@ -51,7 +51,7 @@ class OktaOKTAuthStateTests: XCTestCase { ] OKTURLSessionProvider.setSession(networkMock) - OKTAuthState.getState(withAuthRequest: requestMock, delegate: delegateMock) { (state, _) in + OKTAuthState.getState(withAuthRequest: requestMock, delegate: delegateMock, validator: OKTDefaultTokenValidator()) { (state, _) in let stateDelegate = state?.delegate XCTAssertEqual(stateDelegate as! OktaNetworkRequestCustomizationDelegateMock, delegateMock) authStateExpectation.fulfill() diff --git a/Tests/OktaOidcTests/OktaOidcBrowserTaskMACTests.swift b/Tests/OktaOidcTests/OktaOidcBrowserTaskMACTests.swift index b27a87ed5c4..e8c47804e5a 100644 --- a/Tests/OktaOidcTests/OktaOidcBrowserTaskMACTests.swift +++ b/Tests/OktaOidcTests/OktaOidcBrowserTaskMACTests.swift @@ -80,7 +80,7 @@ class OktaOidcBrowserTaskMACTests: XCTestCase { var browserTask = OktaOidcBrowserTaskMACPartialMock(config: config, oktaAPI: OktaOidcApiMock(), redirectServerConfiguration: OktaRedirectServerConfiguration.default) - browserTask.signIn { _, _ in + browserTask.signIn(validator: OKTDefaultTokenValidator()) { _, _ in XCTAssertTrue(browserTask.downloadOidcConfigCalled) signInExpectation.fulfill() } @@ -90,7 +90,7 @@ class OktaOidcBrowserTaskMACTests: XCTestCase { signInExpectation = expectation(description: "Completion should be called!") browserTask = OktaOidcBrowserTaskMACPartialMock(config: config, oktaAPI: OktaOidcApiMock()) - browserTask.signIn { _, _ in + browserTask.signIn(validator: OKTDefaultTokenValidator()) { _, _ in XCTAssertTrue(browserTask.downloadOidcConfigCalled) signInExpectation.fulfill() } diff --git a/okta-oidc.xcodeproj/project.pbxproj b/okta-oidc.xcodeproj/project.pbxproj index 0575f0b35fb..21fba985b69 100644 --- a/okta-oidc.xcodeproj/project.pbxproj +++ b/okta-oidc.xcodeproj/project.pbxproj @@ -39,6 +39,14 @@ 92AF826326209E1C004D157D /* OktaOidcHttpApiProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 922628782617553E002F6BC4 /* OktaOidcHttpApiProtocol.swift */; }; 92B62A2D25C41E59002CE64F /* OKTTokensAuthMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B62A2C25C41E59002CE64F /* OKTTokensAuthMock.swift */; }; 92B62A2E25C41E59002CE64F /* OKTTokensAuthMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B62A2C25C41E59002CE64F /* OKTTokensAuthMock.swift */; }; + 92C1DF5B27A15F1C003773F5 /* OKTDefaultTokenValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C1DF5927A15F1B003773F5 /* OKTDefaultTokenValidator.m */; }; + 92C1DF5C27A2FA82003773F5 /* OKTDefaultTokenValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C1DF5927A15F1B003773F5 /* OKTDefaultTokenValidator.m */; }; + 92C1DF6027A459BC003773F5 /* OKTDefaultTokenValidatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C1DF5F27A459BC003773F5 /* OKTDefaultTokenValidatorTests.m */; }; + 92C1DF6127A47347003773F5 /* OKTDefaultTokenValidatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 92C1DF5F27A459BC003773F5 /* OKTDefaultTokenValidatorTests.m */; }; + 92C1DF6427A84FDF003773F5 /* OKTDefaultTokenValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 92C1DF6327A84FDE003773F5 /* OKTDefaultTokenValidator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 92C1DF6527A84FDF003773F5 /* OKTDefaultTokenValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 92C1DF6327A84FDE003773F5 /* OKTDefaultTokenValidator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 92C1DF6727A84FFF003773F5 /* OKTTokenValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 92C1DF6627A84FFF003773F5 /* OKTTokenValidator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 92C1DF6827A84FFF003773F5 /* OKTTokenValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = 92C1DF6627A84FFF003773F5 /* OKTTokenValidator.h */; settings = {ATTRIBUTES = (Public, ); }; }; 92DB056B2751129E00B3714F /* OktaOidcErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92DB05692751125C00B3714F /* OktaOidcErrorTests.swift */; }; 9601C34C256DD14800C084F5 /* OktaRedirectServerConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A167889D2433C7B500D1651D /* OktaRedirectServerConfigurationTests.swift */; }; 9601C34D256DD14800C084F5 /* OktaOidcBrowserTaskMACTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A167889F2433D0DB00D1651D /* OktaOidcBrowserTaskMACTests.swift */; }; @@ -378,6 +386,11 @@ 922628782617553E002F6BC4 /* OktaOidcHttpApiProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaOidcHttpApiProtocol.swift; sourceTree = ""; }; 922628DA261B1F90002F6BC4 /* XCUIElement+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Utils.swift"; sourceTree = ""; }; 92B62A2C25C41E59002CE64F /* OKTTokensAuthMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OKTTokensAuthMock.swift; sourceTree = ""; }; + 92C1DF5927A15F1B003773F5 /* OKTDefaultTokenValidator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OKTDefaultTokenValidator.m; sourceTree = ""; }; + 92C1DF5E27A459BC003773F5 /* OKTDefaultTokenValidatorTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OKTDefaultTokenValidatorTests.h; sourceTree = ""; }; + 92C1DF5F27A459BC003773F5 /* OKTDefaultTokenValidatorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OKTDefaultTokenValidatorTests.m; sourceTree = ""; }; + 92C1DF6327A84FDE003773F5 /* OKTDefaultTokenValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTDefaultTokenValidator.h; path = include/OKTDefaultTokenValidator.h; sourceTree = ""; }; + 92C1DF6627A84FFF003773F5 /* OKTTokenValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTTokenValidator.h; path = include/OKTTokenValidator.h; sourceTree = ""; }; 92DB05692751125C00B3714F /* OktaOidcErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaOidcErrorTests.swift; sourceTree = ""; }; 960961F925672EC40077978A /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 9671A102256F153900D0B03F /* OktaOidcBrowserProtocolIOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OktaOidcBrowserProtocolIOS.swift; path = Internal/OktaOidcBrowserProtocolIOS.swift; sourceTree = ""; }; @@ -411,7 +424,7 @@ A17E3844234CFEE700837873 /* OKTServiceConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTServiceConfiguration.m; sourceTree = ""; }; A17E3845234CFEE700837873 /* OKTTokenUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTTokenUtilities.m; sourceTree = ""; }; A17E3846234CFEE700837873 /* OKTURLQueryComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTURLQueryComponent.m; sourceTree = ""; }; - A17E3847234CFEE700837873 /* OKTAuthorizationService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTAuthorizationService.h; path = include/OKTAuthorizationService.h; sourceTree = ""; }; + A17E3847234CFEE700837873 /* OKTAuthorizationService.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = OKTAuthorizationService.h; path = include/OKTAuthorizationService.h; sourceTree = ""; tabWidth = 2; }; A17E3848234CFEE700837873 /* OKTEndSessionResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTEndSessionResponse.h; path = include/OKTEndSessionResponse.h; sourceTree = ""; }; A17E384A234CFEE800837873 /* OKTIDToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTIDToken.m; sourceTree = ""; }; A17E384B234CFEE800837873 /* OKTAuthState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTAuthState.h; path = include/OKTAuthState.h; sourceTree = ""; }; @@ -439,7 +452,7 @@ A17E3862234CFEEA00837873 /* OKTScopes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTScopes.m; sourceTree = ""; }; A17E3864234CFEEA00837873 /* OKTURLQueryComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTURLQueryComponent.h; path = include/OKTURLQueryComponent.h; sourceTree = ""; }; A17E3865234CFEEA00837873 /* OKTRegistrationResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTRegistrationResponse.m; sourceTree = ""; }; - A17E3866234CFEEB00837873 /* OKTAuthorizationService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTAuthorizationService.m; sourceTree = ""; }; + A17E3866234CFEEB00837873 /* OKTAuthorizationService.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = OKTAuthorizationService.m; sourceTree = ""; tabWidth = 2; }; A17E3867234CFEEB00837873 /* OKTTokenRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTTokenRequest.h; path = include/OKTTokenRequest.h; sourceTree = ""; }; A17E3868234CFEEB00837873 /* OKTAuthorizationResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTAuthorizationResponse.m; sourceTree = ""; }; A17E3869234CFEEB00837873 /* OKTClientMetadataParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTClientMetadataParameters.h; path = include/OKTClientMetadataParameters.h; sourceTree = ""; }; @@ -598,7 +611,6 @@ 2F32CBE5229D4CF8003A6768 /* Tests */, 2F32CC89229D4FCD003A6768 /* UITests */, 2F32CA1F229D38D4003A6768 /* Products */, - 2F32CBD2229D42D0003A6768 /* Frameworks */, ); indentWidth = 4; sourceTree = ""; @@ -662,13 +674,6 @@ path = Example; sourceTree = ""; }; - 2F32CBD2229D42D0003A6768 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ); - name = Frameworks; - sourceTree = ""; - }; 2F32CBE5229D4CF8003A6768 /* Tests */ = { isa = PBXGroup; children = ( @@ -713,6 +718,8 @@ A17E39F52358FA3000837873 /* OKTURLQueryComponentTests.m */, A17E39F32358FA3000837873 /* OKTURLQueryComponentTestsIOS7.m */, A17E39F62358FA3000837873 /* OKTURLSessionProviderTests.m */, + 92C1DF5E27A459BC003773F5 /* OKTDefaultTokenValidatorTests.h */, + 92C1DF5F27A459BC003773F5 /* OKTDefaultTokenValidatorTests.m */, ); path = AppAuthTests; sourceTree = ""; @@ -881,6 +888,9 @@ A17E3846234CFEE700837873 /* OKTURLQueryComponent.m */, A17E384E234CFEE800837873 /* OKTURLSessionProvider.h */, A17E3856234CFEE900837873 /* OKTURLSessionProvider.m */, + 92C1DF6627A84FFF003773F5 /* OKTTokenValidator.h */, + 92C1DF6327A84FDE003773F5 /* OKTDefaultTokenValidator.h */, + 92C1DF5927A15F1B003773F5 /* OKTDefaultTokenValidator.m */, ); name = Core; sourceTree = ""; @@ -1006,6 +1016,7 @@ files = ( A17E3887234CFEED00837873 /* OKTAuthorizationResponse.h in Headers */, A17E387A234CFEED00837873 /* AppAuthCore.h in Headers */, + 92C1DF6427A84FDF003773F5 /* OKTDefaultTokenValidator.h in Headers */, A17E3893234CFEED00837873 /* OKTError.h in Headers */, A17E38A3234CFEED00837873 /* OKTFieldMapping.h in Headers */, A17E3890234CFEED00837873 /* OKTGrantTypes.h in Headers */, @@ -1020,6 +1031,7 @@ A17E3895234CFEED00837873 /* OKTScopes.h in Headers */, A17E38A1234CFEED00837873 /* OKTClientMetadataParameters.h in Headers */, A17E3891234CFEED00837873 /* OKTTokenUtilities.h in Headers */, + 92C1DF6727A84FFF003773F5 /* OKTTokenValidator.h in Headers */, A17E388A234CFEED00837873 /* OKTExternalUserAgentSession.h in Headers */, A17E38AF234CFEED00837873 /* OKTTokenResponse.h in Headers */, A17E388B234CFEED00837873 /* OKTExternalUserAgent.h in Headers */, @@ -1052,6 +1064,7 @@ files = ( A17E397A234D2EC900837873 /* OKTLoopbackHTTPServer.h in Headers */, A17E397B234D2EC900837873 /* OKTAuthorizationService+Mac.h in Headers */, + 92C1DF6527A84FDF003773F5 /* OKTDefaultTokenValidator.h in Headers */, A17E397C234D2ECA00837873 /* OKTAuthState+Mac.h in Headers */, A17E397D234D2ECA00837873 /* OKTExternalUserAgentMac.h in Headers */, A17E397E234D2ECA00837873 /* OKTRedirectHTTPHandler.h in Headers */, @@ -1066,6 +1079,7 @@ A17E395F234D2EAA00837873 /* OKTEndSessionRequest.h in Headers */, A17E3960234D2EAA00837873 /* OKTEndSessionResponse.h in Headers */, A17E3961234D2EAA00837873 /* OKTError.h in Headers */, + 92C1DF6827A84FFF003773F5 /* OKTTokenValidator.h in Headers */, A17E3962234D2EAA00837873 /* OKTErrorUtilities.h in Headers */, A17E3963234D2EAA00837873 /* OKTExternalUserAgent.h in Headers */, A17E3964234D2EAA00837873 /* OKTExternalUserAgentRequest.h in Headers */, @@ -1213,7 +1227,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1100; - LastUpgradeCheck = 1240; + LastUpgradeCheck = 1310; ORGANIZATIONNAME = Okta; TargetAttributes = { 2F32CA1D229D38D4003A6768 = { @@ -1362,6 +1376,7 @@ A17E387E234CFEED00837873 /* OKTURLQueryComponent.m in Sources */, A17E38BF234CFF1E00837873 /* OKTAuthorizationService+IOS.m in Sources */, A17E38C0234CFF1E00837873 /* OKTExternalUserAgentIOS.m in Sources */, + 92C1DF5B27A15F1C003773F5 /* OKTDefaultTokenValidator.m in Sources */, 9671A104256F153900D0B03F /* OktaOidcBrowserProtocolIOS.swift in Sources */, A17E38B1234CFEED00837873 /* OKTClientMetadataParameters.m in Sources */, A17E39E32357DB6800837873 /* OktaOidcAuthenticate.swift in Sources */, @@ -1461,6 +1476,7 @@ A17E3A142358FA3300837873 /* OKTURLQueryComponentTests.m in Sources */, 2F32CC3B229D4D11003A6768 /* OktaOidcEndpointTests.swift in Sources */, A10FA55624B6310500E00620 /* OIDExternalUserAgentNoSsoTests.swift in Sources */, + 92C1DF6027A459BC003773F5 /* OKTDefaultTokenValidatorTests.m in Sources */, A16788C12436B1DF00D1651D /* OKTExternalUserAgentSessionMock.swift in Sources */, 2F32CC3E229D4D11003A6768 /* OktaOidcStateManagerTests.swift in Sources */, ); @@ -1525,6 +1541,7 @@ A17E393C234D2E7100837873 /* OKTServiceDiscovery.m in Sources */, A17E39A0235135FE00837873 /* OktaRedirectServer.swift in Sources */, A17E393D234D2E7100837873 /* OKTTokenRequest.m in Sources */, + 92C1DF5C27A2FA82003773F5 /* OKTDefaultTokenValidator.m in Sources */, A17E393E234D2E7100837873 /* OKTTokenResponse.m in Sources */, A17E393F234D2E7100837873 /* OKTTokenUtilities.m in Sources */, A17E39CD2357DB0F00837873 /* OktaOidcRestApi.swift in Sources */, @@ -1546,6 +1563,7 @@ A16788CB2437F7F500D1651D /* OIDAuthorizationServiceMACMock.swift in Sources */, A167889C2432CDD800D1651D /* OKTRedirectHTTPHandlerMock.swift in Sources */, A167889E2433C7B500D1651D /* OktaRedirectServerConfigurationTests.swift in Sources */, + 92C1DF6127A47347003773F5 /* OKTDefaultTokenValidatorTests.m in Sources */, A16788C22436B1DF00D1651D /* OKTExternalUserAgentSessionMock.swift in Sources */, 9601C356256DD14900C084F5 /* OIDExternalUserAgentNoSsoTests.swift in Sources */, A16788AE243567A400D1651D /* OktaOidcBrowserTaskMacMock.swift in Sources */, diff --git a/okta-oidc.xcodeproj/xcshareddata/xcschemes/okta-oidc-ios.xcscheme b/okta-oidc.xcodeproj/xcshareddata/xcschemes/okta-oidc-ios.xcscheme index 88ad20fc9a5..0aa5c1aaebd 100644 --- a/okta-oidc.xcodeproj/xcshareddata/xcschemes/okta-oidc-ios.xcscheme +++ b/okta-oidc.xcodeproj/xcshareddata/xcschemes/okta-oidc-ios.xcscheme @@ -1,6 +1,6 @@ - - - - diff --git a/okta-oidc.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/okta-oidc.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d6..00000000000 --- a/okta-oidc.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - -