NXLAuth for iOS is a client SDK for communicating with OAuth 2.0 and OpenID Connect providers. It strives to directly map the requests and responses of those specifications, while following the idiomatic style of the implementation language. In addition to mapping the raw protocol flows, convenience methods are available to assist with common tasks like performing an action with fresh tokens.
It follows the best practices set out in
RFC 8252 - OAuth 2.0 for Native Apps
including using SFAuthenticationSession
and SFSafariViewController
on iOS
for the auth request. UIWebView
and WKWebView
are explicitly not
supported due to the security and usability reasons explained in
Section 8.12 of RFC 8252.
It also supports the PKCE extension to OAuth which was created to secure authorization codes in public clients when custom URI scheme redirects are used. The library is friendly to other extensions (standard or otherwise) with the ability to handle additional params in all protocol requests and responses.
NXLAuth supports iOS 7 and above.
iOS 9+ uses the in-app browser tab pattern
(via SFSafariViewController
), and falls back to the system browser (mobile
Safari) on earlier versions.
Both Custom URI Schemes (all supported versions of iOS) and Universal Links (iOS 9+) can be used with the library.
In general, NXLAuth can work with any Authorization Server (AS) that supports native apps as documented in RFC 8252, either through custom URI scheme redirects, or universal links. AS's that assume all clients are web-based or require clients to maintain confidentiality of the client secrets may not work well.
NXLAuth provide convenience methods to interaction with the Authorization Server
where you perform token exchanges and some of this logic for you. This Demo app uses the
convenience method which returns either an OIDAuthState
object, or an error.
OIDAuthState
is a class that keeps track of the authorization and token
requests and responses, and provides a convenience method to call an API with
fresh tokens. This is the only object that you need to serialize to retain the
authorization state of the session.
Want to try out NXLAuth? Just click HERE to try out our Demo App
Follow the instructions in the Demo app README.md to configure with your own OAuth client (you need to update 3 configuration points with your client info to try the demo).
-
With CocoaPods, add the following line to your
Podfile
:pod 'AppAuth', :git => 'https://github.com/nexlife/AppAuth-iOS.git'
Then run
pod install
.
-
Download the NXLAuth Framework file 👉 HERE 👈
-
Create a NXLAuthConfig.plist in your project. add the following line to your NXLAuthConfig.plist.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NXLAuthConfig</key> <array> <dict> <key>Issuer</key> <string>YOUR ISSUER</string> <key>ClientID</key> <string>YOUR CLIENT ID</string> <key>RedirectURI</key> <string>YOUR REDIRECT URL</string> </dict> </array> </dict> </plist>
- Issuer
- Client ID
- Redirect URI
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NXLAuthConfig</key>
<array>
<dict>
<key>Issuer</key>
<string>YOUR ISSUER</string>
<key>ClientID</key>
<string>YOUR CLIENT ID</string>
<key>RedirectURI</key>
<string>YOUR REDIRECT URL</string>
</dict>
</array>
</dict>
</plist>
First you need to have a property in your AppDelegate to hold the session, in order to continue the authorization flow from the redirect.
// protocol of the app's AppDelegate
@protocol OIDExternalUserAgentSession;
// property of the app's AppDelegate
@property(nonatomic, strong, nullable)
id<OIDExternalUserAgentSession> currentAuthorizationFlow;
And your main class, a property to store the auth state:
// property of the containing class
@property(nonatomic, strong, nullable) OIDAuthState *authState;
Then, initiate the authorization request. By using the
ssoAuthRequest
convenience method, the token
exchange will be performed automatically, and everything will be protected with
PKCE (if the server supports it).
// builds authentication request
AppDelegate *appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
NXLAppAuthManager *nexMng = [[NXLAppAuthManager alloc] init];
NSArray *scopes = @[ ScopeOpenID, ScopeOffline];
[nexMng ssoAuthRequest:scopes :^(OIDAuthorizationRequest *request){
appDelegate.currentAuthorizationFlow = [nexMng ssoAuthStateByPresentingAuthorizationRequest:request presentingViewController:self :^(OIDAuthState * _Nonnull authState) {
if (authState) {
NSLog(@"Got authorization tokens. Access token: %@",
authState.lastTokenResponse.accessToken);
[self setAuthState:authState];
}
}];
}];
Handling the Redirect
The authorization response URL is returned to the app via the iOS openURL app delegate method, so you need to pipe this through to the current authorization session (created in the previous session).
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options {
// Sends the URL to the current authorization flow (if any) which will
// process it if it relates to an authorization response.
if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
_currentAuthorizationFlow = nil;
return YES;
}
// Your additional URL handling (if any) goes here.
return NO;
}
NXLAuth gives you the raw token information, if you need it. However we
recommend that users of the OIDAuthState
convenience wrapper use the provided
getFreshToken:
method to perform their API calls to avoid
needing to worry about token freshness.
NXLAppAuthManager *nexMng = [[NXLAppAuthManager alloc] init];
[nexMng getFreshToken:^(NSString *_Nonnull accessToken,
NSString *_Nonnull idToken,
OIDAuthState * _Nonnull currentAuthState,
NSError *_Nullable error) {
if (error) {
NSLog(@"Error fetching fresh tokens: %@", [error localizedDescription]);
return;
}
// perform your API request using the tokens
}];
The universal framework will run on both simulators and Devices. But still there is a problem.
Need to remove unused architectures before submit to Apple app store. Because Apple doesn’t allow the application with unused architectures to the App Store. Please make sure that you have Remove Unused Architectures Script added in your project while releasing your app to app store.
Select the Project, Choose Target → Project Name → Select Build Phases → Press “+” → New Run Script Phase → Name the Script as “Remove Unused Architectures Script”.
if [ "${CONFIGURATION}" = "Release" ]; then
FRAMEWORK="NXLAuth"
FRAMEWORK_EXECUTABLE_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/$FRAMEWORK.framework/$FRAMEWORK"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
fi
This run script removes the unused Simulator architectures only while pushing the Application to the App Store.
Browse the API documentation.
Sample apps that explore core NXLAuth features are available for iOS, follow the instructions in Examples repo to get started.