Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a configuration property populated via Info.plist #228

Merged
merged 10 commits into from
Sep 29, 2022
117 changes: 81 additions & 36 deletions GoogleSignIn/Sources/GIDSignIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@
// Minimum time to expiration for a restored access token.
static const NSTimeInterval kMinimumRestoredAccessTokenTimeToExpire = 600.0;

// Info.plist config keys
static NSString *const kConfigClientIDKey = @"GIDClientID";
static NSString *const kConfigServerClientIDKey = @"GIDServerClientID";
static NSString *const kConfigHostedDomainKey = @"GIDHostedDomain";
static NSString *const kConfigOpenIDRealmKey = @"GIDOpenIDRealm";

// The callback queue used for authentication flow.
@interface GIDAuthFlow : GIDCallbackQueue

Expand Down Expand Up @@ -214,26 +220,24 @@ - (BOOL)restorePreviousSignInNoRefresh {

#if TARGET_OS_IOS || TARGET_OS_MACCATALYST

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion {
- (void)signInWithPresentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion {
GIDSignInInternalOptions *options =
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
[GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration
presentingViewController:presentingViewController
loginHint:hint
addScopesFlow:NO
completion:completion];
[self signInWithOptions:options];
}

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion {
- (void)signInWithPresentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion {
GIDSignInInternalOptions *options =
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
[GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration
presentingViewController:presentingViewController
loginHint:hint
addScopesFlow:NO
Expand All @@ -242,13 +246,11 @@ - (void)signInWithConfiguration:(GIDConfiguration *)configuration
[self signInWithOptions:options];
}

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
completion:(nullable GIDSignInCompletion)completion {
[self signInWithConfiguration:configuration
presentingViewController:presentingViewController
hint:nil
completion:completion];
- (void)signInWithPresentingViewController:(UIViewController *)presentingViewController
completion:(nullable GIDSignInCompletion)completion {
[self signInWithPresentingViewController:presentingViewController
hint:nil
completion:completion];
}

- (void)addScopes:(NSArray<NSString *> *)scopes
Expand Down Expand Up @@ -307,35 +309,31 @@ - (void)addScopes:(NSArray<NSString *> *)scopes

#elif TARGET_OS_OSX

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion {
- (void)signInWithPresentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion {
GIDSignInInternalOptions *options =
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
[GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration
presentingWindow:presentingWindow
loginHint:hint
addScopesFlow:NO
completion:completion];
[self signInWithOptions:options];
}

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingWindow:(NSWindow *)presentingWindow
completion:(nullable GIDSignInCompletion)completion {
[self signInWithConfiguration:configuration
presentingWindow:presentingWindow
hint:nil
completion:completion];
- (void)signInWithPresentingWindow:(NSWindow *)presentingWindow
completion:(nullable GIDSignInCompletion)completion {
[self signInWithPresentingWindow:presentingWindow
hint:nil
completion:completion];
}

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion {
- (void)signInWithPresentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion {
GIDSignInInternalOptions *options =
[GIDSignInInternalOptions defaultOptionsWithConfiguration:configuration
[GIDSignInInternalOptions defaultOptionsWithConfiguration:_configuration
presentingWindow:presentingWindow
loginHint:hint
addScopesFlow:NO
Expand Down Expand Up @@ -477,6 +475,45 @@ + (GIDSignIn *)sharedInstance {
- (id)initPrivate {
self = [super init];
if (self) {
// Get the app's main bundle.
NSBundle *bundle = [NSBundle mainBundle];

// Retrieve any config parameters from the main bundle.
NSString *clientID;
id configClientID = [bundle objectForInfoDictionaryKey:kConfigClientIDKey];
if ([configClientID isKindOfClass:[NSString class]]) {
clientID = configClientID;
}

NSString *serverClientID;
id configServerClientID = [bundle objectForInfoDictionaryKey:kConfigServerClientIDKey];
if ([configServerClientID isKindOfClass:[NSString class]]) {
serverClientID = configServerClientID;
}

NSString *hostedDomain;
id configHostedDomain = [bundle objectForInfoDictionaryKey:kConfigHostedDomainKey];
if ([configHostedDomain isKindOfClass:[NSString class]]) {
hostedDomain = configHostedDomain;
}

NSString *openIDRealm;
id configopenIDRealm = [bundle objectForInfoDictionaryKey:kConfigOpenIDRealmKey];
if ([configopenIDRealm isKindOfClass:[NSString class]]) {
openIDRealm = configopenIDRealm;
}

// Try to construct an initial configuration. We need at least a client ID.
GIDConfiguration *configuration;
petea marked this conversation as resolved.
Show resolved Hide resolved
if (clientID) {
petea marked this conversation as resolved.
Show resolved Hide resolved
configuration = [[GIDConfiguration alloc] initWithClientID:clientID
serverClientID:serverClientID
hostedDomain:hostedDomain
openIDRealm:openIDRealm];
// Set the initial active configuation
_configuration = configuration;
}

// Check to see if the 3P app is being run for the first time after a fresh install.
BOOL isFreshInstall = [self isFreshInstall];

Expand Down Expand Up @@ -514,6 +551,14 @@ - (void)signInWithOptions:(GIDSignInInternalOptions *)options {
}

if (options.interactive) {
// Ensure that a configuration has been provided.
if (!_configuration) {
// NOLINTNEXTLINE(google-objc-avoid-throwing-exception)
[NSException raise:NSInvalidArgumentException
format:@"No active configuration. Make sure GIDClientID is set in Info.plist."];
return;
}

// Explicitly throw exception for missing client ID here. This must come before
// scheme check because schemes rely on reverse client IDs.
[self assertValidParameters];
Expand Down
63 changes: 27 additions & 36 deletions GoogleSignIn/Sources/Public/GoogleSignIn/GIDSignIn.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
/// The `GIDGoogleUser` object representing the current user or `nil` if there is no signed-in user.
@property(nonatomic, readonly, nullable) GIDGoogleUser *currentUser;

/// The active configuration for this instance of `GIDSignIn`.
@property(nonatomic, nullable) GIDConfiguration *configuration;
petea marked this conversation as resolved.
Show resolved Hide resolved

/// Unavailable. Use the `sharedInstance` property to instantiate `GIDSignIn`.
/// :nodoc:
+ (instancetype)new NS_UNAVAILABLE;
Expand Down Expand Up @@ -106,53 +109,48 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
- (void)disconnectWithCompletion:(nullable GIDDisconnectCompletion)completion;

#if TARGET_OS_IOS || TARGET_OS_MACCATALYST
/// Starts an interactive sign-in flow on iOS using the provided configuration.
/// Starts an interactive sign-in flow on iOS.
///
/// The completion will be called at the end of this process. Any saved sign-in state will be
/// replaced by the result of this flow. Note that this method should not be called when the app is
/// starting up, (e.g in `application:didFinishLaunchingWithOptions:`); instead use the
/// `restorePreviousSignInWithCompletion:` method to restore a previous sign-in.
///
/// @param configuration The configuration properties to be used for this flow.
/// @param presentingViewController The view controller used to present `SFSafariViewContoller` on
/// iOS 9 and 10 and to supply `presentationContextProvider` for `ASWebAuthenticationSession` on
/// iOS 13+.
/// @param completion The `GIDSignInCompletion` block that is called on completion. This block will
/// be called asynchronously on the main queue.
- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
completion:(nullable GIDSignInCompletion)completion
- (void)signInWithPresentingViewController:(UIViewController *)presentingViewController
completion:(nullable GIDSignInCompletion)completion
NS_EXTENSION_UNAVAILABLE("The sign-in flow is not supported in App Extensions.");

/// Starts an interactive sign-in flow on iOS using the provided configuration and a login hint.
/// Starts an interactive sign-in flow on iOS using the provided hint.
///
/// The completion will be called at the end of this process. Any saved sign-in state will be
/// replaced by the result of this flow. Note that this method should not be called when the app is
/// starting up, (e.g in `application:didFinishLaunchingWithOptions:`); instead use the
/// `restorePreviousSignInWithCompletion:` method to restore a previous sign-in.
///
/// @param configuration The configuration properties to be used for this flow.
/// @param presentingViewController The view controller used to present `SFSafariViewContoller` on
/// iOS 9 and 10 and to supply `presentationContextProvider` for `ASWebAuthenticationSession` on
/// iOS 13+.
/// @param hint An optional hint for the authorization server, for example the user's ID or email
/// address, to be prefilled if possible.
/// @param completion The `GIDSignInCompletion` block that is called on completion. This block will
/// be called asynchronously on the main queue.
- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion
- (void)signInWithPresentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion
NS_EXTENSION_UNAVAILABLE("The sign-in flow is not supported in App Extensions.");

/// Starts an interactive sign-in flow on iOS using the provided configuration and a login hint.
/// Starts an interactive sign-in flow on iOS using the provided hint and additional scopes.
///
/// The completion will be called at the end of this process. Any saved sign-in state will be
/// replaced by the result of this flow. Note that this method should not be called when the app is
/// starting up, (e.g in `application:didFinishLaunchingWithOptions:`); instead use the
/// `restorePreviousSignInWithCompletion:` method to restore a previous sign-in.
///
/// @param configuration The configuration properties to be used for this flow.
/// @param presentingViewController The view controller used to present `SFSafariViewContoller` on
/// iOS 9 and 10.
/// @param hint An optional hint for the authorization server, for example the user's ID or email
Expand All @@ -161,11 +159,10 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
/// @param completion The `GIDSignInCompletion` block that is called on completion. This block will
/// be called asynchronously on the main queue.

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion;
- (void)signInWithPresentingViewController:(UIViewController *)presentingViewController
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion;

/// Starts an interactive consent flow on iOS to add scopes to the current user's grants.
///
Expand All @@ -184,59 +181,53 @@ typedef void (^GIDDisconnectCompletion)(NSError *_Nullable error);
NS_EXTENSION_UNAVAILABLE("The add scopes flow is not supported in App Extensions.");

#elif TARGET_OS_OSX
/// Starts an interactive sign-in flow on macOS using the provided configuration.
/// Starts an interactive sign-in flow on macOS.
///
/// The completion will be called at the end of this process. Any saved sign-in state will be
/// replaced by the result of this flow. Note that this method should not be called when the app is
/// starting up, (e.g in `application:didFinishLaunchingWithOptions:`); instead use the
/// `restorePreviousSignInWithCompletion:` method to restore a previous sign-in.
///
/// @param configuration The configuration properties to be used for this flow.
/// @param presentingWindow The window used to supply `presentationContextProvider` for `ASWebAuthenticationSession`.
/// @param completion The `GIDSignInCompletion` block that is called on completion. This block will
/// be called asynchronously on the main queue.
- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingWindow:(NSWindow *)presentingWindow
completion:(nullable GIDSignInCompletion)completion;
- (void)signInWithPresentingWindow:(NSWindow *)presentingWindow
completion:(nullable GIDSignInCompletion)completion;

/// Starts an interactive sign-in flow on macOS using the provided configuration and a login hint.
/// Starts an interactive sign-in flow on macOS using the provided hint.
///
/// The completion will be called at the end of this process. Any saved sign-in state will be
/// replaced by the result of this flow. Note that this method should not be called when the app is
/// starting up, (e.g in `application:didFinishLaunchingWithOptions:`); instead use the
/// `restorePreviousSignInWithCompletion:` method to restore a previous sign-in.
///
/// @param configuration The configuration properties to be used for this flow.
/// @param presentingWindow The window used to supply `presentationContextProvider` for `ASWebAuthenticationSession`.
/// @param hint An optional hint for the authorization server, for example the user's ID or email
/// address, to be prefilled if possible.
/// @param completion The `GIDSignInCompletion` block that is called on completion. This block will
/// be called asynchronously on the main queue.
- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion;
- (void)signInWithPresentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
completion:(nullable GIDSignInCompletion)completion;

/// Starts an interactive sign-in flow on macOS using the provided configuration and a login hint.
/// Starts an interactive sign-in flow on macOS using the provided hint.
///
/// The completion will be called at the end of this process. Any saved sign-in state will be
/// replaced by the result of this flow. Note that this method should not be called when the app is
/// starting up, (e.g in `application:didFinishLaunchingWithOptions:`); instead use the
/// `restorePreviousSignInWithCompletion:` method to restore a previous sign-in.
///
/// @param configuration The configuration properties to be used for this flow.
/// @param presentingWindow The window used to supply `presentationContextProvider` for `ASWebAuthenticationSession`.
/// @param hint An optional hint for the authorization server, for example the user's ID or email
/// address, to be prefilled if possible.
/// @param additionalScopes An optional array of scopes to request in addition to the basic profile scopes.
/// @param completion The `GIDSignInCompletion` block that is called on completion. This block will
/// be called asynchronously on the main queue.

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
presentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion;
- (void)signInWithPresentingWindow:(NSWindow *)presentingWindow
hint:(nullable NSString *)hint
additionalScopes:(nullable NSArray<NSString *> *)additionalScopes
completion:(nullable GIDSignInCompletion)completion;

/// Starts an interactive consent flow on macOS to add scopes to the current user's grants.
///
Expand Down
Loading