diff --git a/GoogleSignIn/Sources/GIDTokenClaim.m b/GoogleSignIn/Sources/GIDTokenClaim.m new file mode 100644 index 00000000..61e83d6a --- /dev/null +++ b/GoogleSignIn/Sources/GIDTokenClaim.m @@ -0,0 +1,75 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDTokenClaim.h" + +NSString * const kAuthTimeClaimName = @"auth_time"; + +// Private interface to declare the internal initializer +@interface GIDTokenClaim () + +- (instancetype)initWithName:(NSString *)name + essential:(BOOL)essential NS_DESIGNATED_INITIALIZER; + +@end + +@implementation GIDTokenClaim + +// Private designated initializer +- (instancetype)initWithName:(NSString *)name essential:(BOOL)essential { + self = [super init]; + if (self) { + _name = [name copy]; + _essential = essential; + } + return self; +} + +#pragma mark - Factory Methods + ++ (instancetype)authTimeClaim { + return [[self alloc] initWithName:kAuthTimeClaimName essential:NO]; +} + ++ (instancetype)essentialAuthTimeClaim { + return [[self alloc] initWithName:kAuthTimeClaimName essential:YES]; +} + +#pragma mark - NSObject + +- (BOOL)isEqual:(id)object { + // 1. Check if the other object is the same instance in memory. + if (self == object) { + return YES; + } + + // 2. Check if the other object is not a GIDTokenClaim instance. + if (![object isKindOfClass:[GIDTokenClaim class]]) { + return NO; + } + + // 3. Compare the properties that define equality. + GIDTokenClaim *other = (GIDTokenClaim *)object; + return [self.name isEqualToString:other.name] && + self.isEssential == other.isEssential; +} + +- (NSUInteger)hash { + // The hash value should be based on the same properties used in isEqual: + return self.name.hash ^ @(self.isEssential).hash; +} + +@end diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GIDTokenClaim.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDTokenClaim.h new file mode 100644 index 00000000..7a2351cb --- /dev/null +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GIDTokenClaim.h @@ -0,0 +1,48 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const kAuthTimeClaimName; + +/** + * An object representing a single OIDC claim to be requested for an ID token. + */ +@interface GIDTokenClaim : NSObject + +/// The name of the claim, e.g., "auth_time". +@property (nonatomic, readonly) NSString *name; + +/// Whether the claim is requested as essential. +@property (nonatomic, readonly, getter=isEssential) BOOL essential; + +// Making initializers unavailable to force use of factory methods. +- (instancetype)init NS_UNAVAILABLE; + +#pragma mark - Factory Methods + +/// Creates a *non-essential* (voluntary) "auth_time" claim object. ++ (instancetype)authTimeClaim; + +/// Creates an *essential* "auth_time" claim object. ++ (instancetype)essentialAuthTimeClaim; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h b/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h index 4fd17ede..02935be8 100644 --- a/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h +++ b/GoogleSignIn/Sources/Public/GoogleSignIn/GoogleSignIn.h @@ -24,6 +24,7 @@ #import "GIDSignIn.h" #import "GIDToken.h" #import "GIDSignInResult.h" +#import "GIDTokenClaim.h" #if TARGET_OS_IOS || TARGET_OS_MACCATALYST #import "GIDSignInButton.h" #endif diff --git a/GoogleSignIn/Tests/Unit/GIDTokenClaimTest.m b/GoogleSignIn/Tests/Unit/GIDTokenClaimTest.m new file mode 100644 index 00000000..145e46f6 --- /dev/null +++ b/GoogleSignIn/Tests/Unit/GIDTokenClaimTest.m @@ -0,0 +1,49 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#import +#import "GoogleSignIn/Sources/Public/GoogleSignIn/GIDTokenClaim.h" + +@interface GIDTokenClaimTest : XCTestCase +@end + +@implementation GIDTokenClaimTest + +- (void)testAuthTimeClaim_PropertiesAreCorrect { + GIDTokenClaim *claim = [GIDTokenClaim authTimeClaim]; + XCTAssertEqualObjects(claim.name, kAuthTimeClaimName); + XCTAssertFalse(claim.isEssential); +} + +- (void)testEssentialAuthTimeClaim_PropertiesAreCorrect { + GIDTokenClaim *claim = [GIDTokenClaim essentialAuthTimeClaim]; + XCTAssertEqualObjects(claim.name, kAuthTimeClaimName); + XCTAssertTrue(claim.isEssential); +} + +- (void)testEquality_WithEqualClaims { + GIDTokenClaim *claim1 = [GIDTokenClaim authTimeClaim]; + GIDTokenClaim *claim2 = [GIDTokenClaim authTimeClaim]; + XCTAssertEqualObjects(claim1, claim2); + XCTAssertEqual(claim1.hash, claim2.hash); +} + +- (void)testEquality_WithUnequalClaims { + GIDTokenClaim *claim1 = [GIDTokenClaim authTimeClaim]; + GIDTokenClaim *claim2 = [GIDTokenClaim essentialAuthTimeClaim]; + XCTAssertNotEqualObjects(claim1, claim2); +} + +@end