TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | Apache 2 |
ReleasedLast Release | Jan 2017 |
SwiftSwift Version | 3.0 |
SPMSupports SPM | ✗ |
Maintained by Edward Jiang, Randall Degges.
The iOS SDK for Stormpath, a framework for authentication & authorization.
iOS 8.0+ / Xcode 8.0+ (Swift 3)
Stormpath’s iOS SDK allows developers utilizing Stormpath to quickly integrate authentication and token management into their apps.
We’re constantly iterating and improving the SDK, so please don’t hesitate to send us your feedback! You can reach us via [email protected], or on the issue tracker for feature requests.
To see the SDK in action, you can try downloading the Stormpath iOS Example project. We’ve built the same app twice, once in Objective-C and another time in Swift so you can see how to use the SDK.
For Swift projects:
import Stormpath
For Objective-C projects:
#import "Stormpath-Swift.h"
The iOS SDK (v3) leverages the Stormpath Client API for its authentication needs. You’ll need to sign into the Stormpath Admin Console to get your Client API details. Go into your Application > Policies > Client API, and ensure that it’s enabled. Copy your Client API URL, and set it in your Xcode project:
Swift:
Stormpath.sharedSession.configuration.APIURL = URL(string: "https://edjiang.apps.stormpath.io")!
Objective-C:
[[SPHStormpath sharedSession] configuration].APIURL = [[NSURL alloc] initWithString:@"https://edjiang.apps.stormpath.io"];
In order to register a user, instantiate a RegistrationForm
object. Stormpath requires an email
and password
to register.
let newUser = RegistrationForm(email: "[email protected]", password: "ExamplePassword")
Then, just invoke the register method on Stormpath
class:
Stormpath.sharedSession.register(account: newUser) { (account, error) -> Void in
guard let account = account where error == nil else {
//The account registration failed
return
}
// Do something with the returned account object, such as save its `href` if needed.
// Registering a user will not automatically log them in.
}
Note: Stormpath callbacks always happen on the main thread, so you can make UI changes directly in the callback.
To log in, collect the email (or username) and password from the user, and then pass them to the login method:
Stormpath.sharedSession.login(username: "[email protected]", password: "ExamplePassword") { success, error in
guard error == nil else {
// We could not authenticate the user with the given credentials. Handle the error.
return
}
// The user is now logged in, and you can use the Stormpath access token to make API requests!
}
Stormpath also supports logging in with a variety of social providers Facebook, Google, LinkedIn, GitHub, and more. There are two flows for enabling this:
We’ve made it extremely easy to set up social login without using the social provider SDKs, but if you need to use their SDKs for more features besides logging in, you should use flow #2 (and skip directly to Using a social provider SDK).
To set up your social directory, read more about social login in the Stormpath Client API Guide.
In your Xcode project, you’ll need to create a URL Scheme so that the login process can call back to your app. Go to the project’s info tab. Under “URL Types”, add a new entry, and in the URL schemes form field, type in your Client API’s DNS label, but reversed. For instance, if your Client API DNS Label is edjiang.apps.stormpath.io
, type in io.stormpath.apps.edjiang
.
In the Stormpath Admin Console’s Application settings, add that URL as an “authorized callback URL”, appending ://stormpathCallback
. Following my earlier example, I would use io.stormpath.apps.edjiang
.
Also, add the following methods to your AppDelegate
in your Xcode project:
// iOS 9+ link handler
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool {
return Stormpath.sharedSession.application(app, open: url, options: options)
}
// iOS 8 and below link handler. Needed if you want to support older iOS
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return Stormpath.sharedSession.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
Now, you can initiate the login screen by calling:
Stormpath.sharedSession.login(provider: .facebook) { (success, error) -> Void in
// This callback is the same as the regular Stormpath.login callback.
// If the user cancels the login, the login was never started, and
// this callback will not be called.
}
If you’re using the Facebook SDK or Google SDK for your app, follow their setup instructions instead. Once you successfully sign in with their SDK, utilize the following methods to send your access token to Stormpath, and log in your user:
Stormpath.sharedSession.login(provider: .facebook, accessToken: FBSDKAccessToken.currentAccessToken().tokenString) { (success, error) -> Void in
// Same callback as above
}
Stormpath.sharedSession.login(provider: .google, accessToken: GIDSignIn.sharedInstance().currentUser.authentication.accessToken) { (success, error) -> Void in
// Same callback as above
}
You can utilize the access token to access any of your API endpoints that require authentication. It’s stored as a property on the Stormpath object as Stormpath.sharedSession.accessToken
. If you need to refresh it, use Stormpath.sharedSession.refreshAccessToken()
. Depending on the networking library you’re using, here’s how you’d use the access token:
var request = URLRequest(URL: url)
request.setValue("Bearer " + accessToken ?? "", forHTTPHeaderField: "Authorization")
let headers = ["Authorization": "Bearer " + accessToken ?? ""]
Alamofire.request(url, method: .get, headers: headers)
Note: As of the iOS 9 SDK, Apple has enabled App Transport Security by default. If you’re developing against an http
endpoint, you’ll need to disable it. For production, you should always be using https
for your API endpoints.
Stormpath’s framework integrations provide a default endpoint for retrieving profile information. Fetch the account data by using me:
Stormpath.sharedSession.me { account, error in
guard let account = account where error == nil else {
// We might not be logged in, the API is misconfigured, the API is down, etc
return
}
// Success! We have the account object.
}
Logging out is simple. This will delete the access token and refresh token from the user’s device, and make an API request to delete from the server.
Stormpath.sharedSession.logout()
To reset a user’s password, you’ll need to collect their email first. Then simply pass that email to the resetPassword
function like so:
Stormpath.sharedSession.resetPassword(email: "[email protected]") { success, error in
guard error == nil else {
// A network or API problem occurred.
return
}
// We succeeded in making the API request.
}
When using Stormpath, you can encounter errors for several reasons:
If there’s a network error, Stormpath will return the NSError
associated with NSURLSession
to your code. Otherwise, Stormpath will return StormpathError
, a NSError
subclass.
For user errors, StormpathError
will have the HTTP error code of the API response (usually 400), and localizedDescription
set to a user-readable error message which is safe to display to the user.
In special cases, StormpathError will have code 0 or 1. These are developer errors that should not be displayed to the user. 0 stands for “Stormpath SDK Error”, and most likely indicates a bug with the Stormpath SDK that should be reported to us. 1 stands for “API Response Error”, and means that the API responded with something unexpected. This most likely means that you have your backend integration misconfigured.
StormpathConfiguration
can be used to point Stormpath to a specific API URL. While you can modify the object directly, you can also put your configuration in Info.plist. To add the Stormpath configuration, right click on Info.plist, and click “open as source code”. Before the last </plist>
tag, paste:
<key>Stormpath</key>
<dict>
<key>APIURL</key>
<string>http://localhost:3000</string>
</dict>
You can modify any of these values, and StormpathConfiguration
will load these on first initialization.
Stormpath can be used to store multiple user accounts, even against multiple API servers using Stormpath. This is useful if you’re making a multi-tenant application that allows the user to be logged in under different accounts at the same time.
To use this feature, instead of using Stormpath.sharedSession
, initialize Stormpath with a custom identifier:
Stormpath(identifier: "newSession")
This will create an instance of Stormpath with the default configuration (shared with the rest of the app) that will store accessTokens
and refreshTokens
in its own partition in the iOS Keychain.
This identifier can be used in your app to identify a user session contained in Stormpath, and properly restore it in between app opens.
Note: the identifier for Stormpath.sharedSession
is “default”, so do not use this as an identifier for another instance of Stormpath.
This project is open-source via Apache 2.0 License. See the LICENSE file for details.