diff --git a/Examples/Example-iOS/.gitignore b/Examples/Example-iOS/.gitignore index 42a22df4..146a0b0e 100644 --- a/Examples/Example-iOS/.gitignore +++ b/Examples/Example-iOS/.gitignore @@ -17,6 +17,9 @@ xcuserdata/ *.moved-aside *.xcuserstate +## Local code-signing / config overrides +Config/Example.local.xcconfig + # Pods are ignored in the samples as all Pods & their dependencies are either # development Pods (this repo) or sourced from repos in the same organization. # Generally we recommend versioning Pods, see the pros & cons here: diff --git a/Examples/Example-iOS/Config/Example.xcconfig b/Examples/Example-iOS/Config/Example.xcconfig new file mode 100644 index 00000000..0ef8ed1b --- /dev/null +++ b/Examples/Example-iOS/Config/Example.xcconfig @@ -0,0 +1,20 @@ +// This file holds public placeholder defaults for the example app's +// bundle identity and code signing. Personal overrides belong in the +// sibling, gitignored Config/Example.local.xcconfig, which overrides +// these defaults via the optional-include directive below. + +PRODUCT_BUNDLE_IDENTIFIER = com.example.GTMAppAuth.Example-iOS + +// OAuth configuration. These placeholder defaults keep the sample building; +// put your real client values in Example.local.xcconfig. +// (The $() in the issuer prevents // from starting an xcconfig comment.) +OIDC_ISSUER = https:/$()/accounts.google.com +OIDC_CLIENT_ID = YOUR_CLIENT.apps.googleusercontent.com +OIDC_REDIRECT_URI = com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect +OIDC_REDIRECT_URI_SCHEME = com.googleusercontent.apps.YOUR_CLIENT + +// Code signing. Defaults to Automatic with no team. Override in +// Example.local.xcconfig if you need Manual signing with a specific provisioning profile. +CODE_SIGN_STYLE = Automatic + +#include? "Example.local.xcconfig" diff --git a/Examples/Example-iOS/Example-iOS.xcodeproj/project.pbxproj b/Examples/Example-iOS/Example-iOS.xcodeproj/project.pbxproj index e6400b1d..72211487 100644 --- a/Examples/Example-iOS/Example-iOS.xcodeproj/project.pbxproj +++ b/Examples/Example-iOS/Example-iOS.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ 34CB09BC1C42007600A54261 /* GTMAppAuthExampleViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GTMAppAuthExampleViewController.xib; sourceTree = ""; }; 738386922954FEF3000BF191 /* GTMAppAuth */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = GTMAppAuth; path = ../..; sourceTree = ""; }; C1AF3AE928187F71003BAEFF /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + C1C0F1D02E2F000000000001 /* Config/Example.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config/Example.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +65,7 @@ children = ( 738386912954FEF3000BF191 /* Packages */, C1AF3AE928187F71003BAEFF /* README.md */, + C1C0F1D02E2F000000000001 /* Config/Example.xcconfig */, 346E916B1C29D42800D3620B /* Source */, 341564001C487ABA00ECA3D9 /* Frameworks */, 346E916A1C29D42800D3620B /* Products */, @@ -297,6 +299,7 @@ }; 346E91811C29D42800D3620B /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = C1C0F1D02E2F000000000001 /* Config/Example.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Source/Info.plist; @@ -309,13 +312,13 @@ "-ObjC", "$(inherited)", ); - PRODUCT_BUNDLE_IDENTIFIER = "com.example.GTMAppAuth.Example-iOS"; PRODUCT_NAME = "Example-iOS"; }; name = Debug; }; 346E91821C29D42800D3620B /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = C1C0F1D02E2F000000000001 /* Config/Example.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Source/Info.plist; @@ -328,7 +331,6 @@ "-ObjC", "$(inherited)", ); - PRODUCT_BUNDLE_IDENTIFIER = "com.example.GTMAppAuth.Example-iOS"; PRODUCT_NAME = "Example-iOS"; }; name = Release; diff --git a/Examples/Example-iOS/Example-iOSForPod.xcodeproj/project.pbxproj b/Examples/Example-iOS/Example-iOSForPod.xcodeproj/project.pbxproj index 8e207966..647a889b 100644 --- a/Examples/Example-iOS/Example-iOSForPod.xcodeproj/project.pbxproj +++ b/Examples/Example-iOS/Example-iOSForPod.xcodeproj/project.pbxproj @@ -374,6 +374,10 @@ INFOPLIST_FILE = Source/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OIDC_CLIENT_ID = "YOUR_CLIENT.apps.googleusercontent.com"; + OIDC_ISSUER = "https://accounts.google.com"; + OIDC_REDIRECT_URI = "com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect"; + OIDC_REDIRECT_URI_SCHEME = "com.googleusercontent.apps.YOUR_CLIENT"; OTHER_LDFLAGS = ( "-ObjC", "$(inherited)", @@ -392,6 +396,10 @@ INFOPLIST_FILE = Source/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OIDC_CLIENT_ID = "YOUR_CLIENT.apps.googleusercontent.com"; + OIDC_ISSUER = "https://accounts.google.com"; + OIDC_REDIRECT_URI = "com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect"; + OIDC_REDIRECT_URI_SCHEME = "com.googleusercontent.apps.YOUR_CLIENT"; OTHER_LDFLAGS = ( "-ObjC", "$(inherited)", diff --git a/Examples/Example-iOS/README.md b/Examples/Example-iOS/README.md index 9518165f..f5d6a670 100644 --- a/Examples/Example-iOS/README.md +++ b/Examples/Example-iOS/README.md @@ -2,7 +2,7 @@ ## Getting Started -Choose which package manager you'd like to use. +Choose which package manager you'd like to use. Note that Cocoapods is in maintenance mode, and the sample project will be removed soon. Use of SPM is strongly suggested. ### Swift Package Manager @@ -30,7 +30,7 @@ $ open Example-iOSForPod.xcworkspace ## Configuration -The example doesn't work out of the box, you need to configure it your own +The example doesn't work out of the box, you need to configure it with your own client ID. ### Creating a Google OAuth Client @@ -42,27 +42,55 @@ Follow the instructions to configure the consent screen (just the Product Name is needed). Then, complete the OAuth client creation by selecting "iOS" as the Application -type. Enter the Bundle ID of the project (`net.openid.appauth.Example` by -default, but you may want to change this in the project and use your own +type. Enter the Bundle ID of the project (`com.example.GTMAppAuth.Example-iOS` +by default, but you may want to change this — via `PRODUCT_BUNDLE_IDENTIFIER` +in `Config/Example.local.xcconfig` for the Swift Package Manager project, or in +the target's build settings for the CocoaPods project — and use your own Bundle ID). Copy the client ID to the clipboard. ### Configure the Example -In `GTMAppAuthExampleViewController.m` update `kClientID` with your new client -id. +The OAuth client configuration is injected at build time via the `OIDC_*` +build settings, which flow into `Info.plist` and are read by +`GTMAppAuthExampleViewController.m` at runtime. -In the same file, update `kRedirectURI` with the *reverse DNS notation* form -of the client ID. For example, if the client ID is -`YOUR_CLIENT.apps.googleusercontent.com`, the reverse DNS notation would be -`com.googleusercontent.apps.YOUR_CLIENT`. A path component is added resulting in -`com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect`. +The values you'll set are: -Finally, open `Info.plist` and fully expand "URL types" (a.k.a. -"CFBundleURLTypes") and replace `com.googleusercontent.apps.YOUR_CLIENT` with -the reverse DNS notation form of your client id (not including the -`:/oauthredirect` path component). +- `OIDC_CLIENT_ID` — your client ID, e.g. `YOUR_CLIENT.apps.googleusercontent.com`. +- `OIDC_REDIRECT_URI` — the *reverse DNS notation* form of the client ID with a + path component appended. For example, if the client ID is + `YOUR_CLIENT.apps.googleusercontent.com`, the reverse DNS notation would be + `com.googleusercontent.apps.YOUR_CLIENT`, resulting in + `com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect`. +- `OIDC_REDIRECT_URI_SCHEME` — the scheme of the redirect URI (the reverse DNS + notation form of your client ID, without the `:/oauthredirect` path + component). This is registered as the app's custom URL scheme + ("CFBundleURLTypes") automatically. -Once you have made those three changes, the sample should be ready to try with -your new OAuth client. +#### Swift Package Manager project + +Create the gitignored file `Config/Example.local.xcconfig` next to the tracked +`Config/Example.xcconfig`, overriding the placeholder defaults: + +``` +OIDC_CLIENT_ID = YOUR_CLIENT.apps.googleusercontent.com +OIDC_REDIRECT_URI = com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect +OIDC_REDIRECT_URI_SCHEME = com.googleusercontent.apps.YOUR_CLIENT +``` + +You can also set code-signing overrides there (`CODE_SIGN_STYLE`, +`DEVELOPMENT_TEAM`, `PROVISIONING_PROFILE_SPECIFIER`, +`PRODUCT_BUNDLE_IDENTIFIER`) to build for a physical device — see the comments +in `Config/Example.xcconfig`. + +#### CocoaPods project + +The `Example-iOSForPod` project's base configuration is owned by CocoaPods, so +it does not use `Config/Example.xcconfig`. Instead, edit the `OIDC_*` +User-Defined build settings directly on the `Example-iOSForPod` target +(Build Settings → User-Defined), replacing the `YOUR_CLIENT` placeholder +values. + +Once configured, the sample should be ready to try with your new OAuth client. diff --git a/Examples/Example-iOS/Source/GTMAppAuthExampleViewController.m b/Examples/Example-iOS/Source/GTMAppAuthExampleViewController.m index 8d13c588..1f6ea48d 100644 --- a/Examples/Example-iOS/Source/GTMAppAuthExampleViewController.m +++ b/Examples/Example-iOS/Source/GTMAppAuthExampleViewController.m @@ -31,24 +31,29 @@ #import "AppDelegate.h" /*! @brief The OIDC issuer from which the configuration will be discovered. + @discussion Populated from Info.plist ("OIDCIssuer" key), which in turn is set from the + OIDC_ISSUER build setting in Config/Example.xcconfig (override in + Config/Example.local.xcconfig). */ -static NSString *const kIssuer = @"https://accounts.google.com"; +#define kIssuer ((NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"OIDCIssuer"]) /*! @brief The OAuth client ID. @discussion For Google, register your client at https://console.developers.google.com/apis/credentials?project=_ - The client should be registered with the "iOS" type. + The client should be registered with the "iOS" type. Populated from Info.plist + ("OIDCClientID" key) via the OIDC_CLIENT_ID build setting in + Config/Example.local.xcconfig. */ -static NSString *const kClientID = @"YOUR_CLIENT.apps.googleusercontent.com"; +#define kClientID ((NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"OIDCClientID"]) /*! @brief The OAuth redirect URI for the client @c kClientID. @discussion With Google, the scheme of the redirect URI is the reverse DNS notation of the client ID. This scheme must be registered as a scheme in the project's Info - property list ("CFBundleURLTypes" plist key). Any path component will work, we use - 'oauthredirect' here to help disambiguate from any other use of this scheme. + property list ("CFBundleURLTypes" plist key). Populated from Info.plist + ("OIDCRedirectURI" key) via the OIDC_REDIRECT_URI build setting in + Config/Example.local.xcconfig. */ -static NSString *const kRedirectURI = - @"com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect"; +#define kRedirectURI ((NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"OIDCRedirectURI"]) /*! @brief The key used to store our `GTMAuthSession` in the keychain. */ @@ -71,17 +76,17 @@ - (void)viewDidLoad { // NOTE: // // To run this sample, you need to register your own iOS client at - // https://console.developers.google.com/apis/credentials?project=_ and update three configuration - // points in the sample: kClientID and kRedirectURI constants in AppAuthExampleViewController.m - // and the URI scheme in Info.plist (URL Types -> Item 0 -> URL Schemes -> Item 0). + // https://console.developers.google.com/apis/credentials?project=_ and set the + // OIDC_CLIENT_ID, OIDC_REDIRECT_URI, and OIDC_REDIRECT_URI_SCHEME build settings in + // Config/Example.local.xcconfig (see Config/Example.xcconfig for the placeholder defaults). // Full instructions: https://github.com/openid/AppAuth-iOS/blob/master/Example/README.md NSAssert(![kClientID isEqualToString:@"YOUR_CLIENT.apps.googleusercontent.com"], - @"Update kClientID with your own client ID. " + @"Set OIDC_CLIENT_ID in Config/Example.local.xcconfig to your own client ID. " "Instructions: https://github.com/openid/AppAuth-iOS/blob/master/Example/README.md"); NSAssert(![kRedirectURI isEqualToString:@"com.googleusercontent.apps.YOUR_CLIENT:/oauthredirect"], - @"Update kRedirectURI with your own redirect URI. " + @"Set OIDC_REDIRECT_URI in Config/Example.local.xcconfig to your own redirect URI. " "Instructions: https://github.com/openid/AppAuth-iOS/blob/master/Example/README.md"); // verifies that the custom URI scheme has been updated in the Info.plist @@ -92,8 +97,8 @@ - (void)viewDidLoad { NSString *urlScheme = urlSchemes.firstObject; NSAssert(![urlScheme isEqualToString:@"com.googleusercontent.apps.YOUR_CLIENT"], - @"Configure the URI scheme in Info.plist (URL Types -> Item 0 -> URL Schemes -> Item 0) " - "with the scheme of your redirect URI. Full instructions: " + @"Set OIDC_REDIRECT_URI_SCHEME in Config/Example.local.xcconfig to the scheme of your " + "redirect URI. Full instructions: " "https://github.com/openid/AppAuth-iOS/blob/master/Example/README.md"); #endif // !defined(NS_BLOCK_ASSERTIONS) diff --git a/Examples/Example-iOS/Source/Info.plist b/Examples/Example-iOS/Source/Info.plist index 308626ab..13e7106e 100644 --- a/Examples/Example-iOS/Source/Info.plist +++ b/Examples/Example-iOS/Source/Info.plist @@ -25,12 +25,18 @@ Editor CFBundleURLSchemes - com.googleusercontent.apps.YOUR_CLIENT + $(OIDC_REDIRECT_URI_SCHEME) CFBundleVersion 1 + OIDCClientID + $(OIDC_CLIENT_ID) + OIDCIssuer + $(OIDC_ISSUER) + OIDCRedirectURI + $(OIDC_REDIRECT_URI) LSRequiresIPhoneOS UILaunchStoryboardName diff --git a/README.md b/README.md index c8f6b561..b25e4170 100644 --- a/README.md +++ b/README.md @@ -352,8 +352,10 @@ should save in GTMAppAuth format as described above). ## Included Samples -Try out one of the included sample apps under [Examples](Examples). In the -apps folder run `pod install`, then open the resulting `xcworkspace` file. +Try out one of the included sample apps under [Examples](Examples). Open the +Swift Package Manager project (`Example-iOS.xcodeproj`) directly, or for +CocoaPods run `pod install` in the app's folder and open the resulting +`xcworkspace` file. Be sure to follow the instructions in [Example-iOS/README.md](Examples/Example-iOS/README.md) or