SchibstedAccount iOS SDK
The SchibstedAccount iOS SDK provides you access to Schibsted identity services via the SPiD APIs. It provides the following:
- User management (profiles, logins, signups)
- UI based logins
- Authenticated request and oauth management
Note: The APIs provided by the SDK do not cover the full spectrum of APIs provided by SPiD. If there is functionality missing, please look at the SPiD API reference and open up an issue for an enhancement request.
- Documentation: Here's the documentation to the latest tagged release (which can be different than the version that's in master).
- Contributing: For details on getting up and running if you are thinking of contributing
Setup
CocoaPods
The pod is available as a public cocoapod under the name SchibstedAccount
The SDK is divided in to different subspecs:
pod 'SchibstedAccount'
: this is the default and contains APIs to create aUser
pod 'SchibstedAccount/Manager'
: the default installs the entire SDK. If you want to only use headless login (i.e. no UI libraries included), then just use this.
You may want to include a tracking subspec as well
The UI does some internal tracking, and allows a TrackingEventsHandler
to be set in the UI's configuration.
To fulfill this, you can either implement it yourself or use one which is already implemented.
Internal: There is an internal Schibsted Tracking implementation for the identity SDK availabe here and is available from source "git@github.schibsted.io:CocoaPods/Specs.git
, so in your pod file you may:
pod 'SchibstedIDTracking'
: Adds dependency to the new pulse SDK
Carthage
Add this to your Cartfile
git "git@github.com:schibsted/account-sdk-ios.git"
Then run:
$ carthage bootstrap --platform ios
or
$ carthage update --platform ios
Internal: And, if you also want to include support for tracking events in the identity UI with the new pulse SDK, add this
git "git@github.schibsted.io:spt-identity/identity-sdk-ios-tracking"
Carthage will build the frameworks you need to link in your project, so make sure you follow these steps to include all of them in your project and you should be up and running. If there is something missing -> email us.
Get some client credentials
The SDK works by giving you access to Schibsted users. And what kind of access is allowed is determined by a set of client credentials. The first thing you must do is get some credentials, which can be done through self service. Learn about environments and merchants.
NOTE: The SDK will not work across environments or merchants.
Usage
The most common use case is to get a hold of a User
object. You can obtain a User object by using a visual or a headless login process. The visual login is the recommended approach, but if the need arises the headless approach is also documented, but not "officially" supported.
Set your client configuration
See above for getting credentials. But once you have them you have to set up a ClientConfiguration
object:
extension SchibstedAccount.ClientConfiguration {
static let `default` = ClientConfiguration(
environment: .preproduction,
clientID: "<your-client-code>",
clientSecret: "<your-client-secret>",
appURLScheme: nil
)
}
All these fields must be retrieved from the selfservice portal. If you set appURLScheme
to nil then the SDK assumes the defult scheme which is spid-<your-client-code>
. Please double check that this is the same as the default scheme as listed in your Redirect URI tab in self service.
Check if you already have a user
Get the last user that was logged in with the SDK
let user = User.loadLast(clientConfiguration: .default);
user.delegate = //...
switch user.state {
case .loggedIn:
// Yay, carry on with app
case .loggedOut:
// Ok, fire up the IdentityUI
}
Even if there was no user persisted to the keychain, this function will return an initialized user object. Checking the state
of the user tells you if the keychain data "looks" valid.
Note: however that the data may have expired even though it is in the keychain, in which case the SDK will try and refresh it automatically for you if you make any requests using the provided extension on URLSession
.
Visual login with IdentityUI
To start the login process you can fire up an IdentityUI
object with an IdentityUIConfiguration
(this is different than the ClientConfiguration
) and it will create a User
object for you if everything goes right. It is recommended to use the IdentityUI to create a User object because it makes sure that the correct login flows supported by the Schibsted Identity backend are adhered to (ie: required fields are filled in, and terms and conditions are accepted, etc).
Logging in with the IdentityUI
import UIKit
import SchibstedAccount
extension IdentityUIConfiguration {
// See docs for more options
static let `default` = IdentityUIConfiguration(
clientConfiguration: .default,
isCancelable: true,
isSkippable: true
)
}
class ViewController: UIViewController {
var identityUI: IdentityUI?
var user: User?
@IBAction func didTapLoginButton(_ sender: UIButton) {
let identifierType: IdentifierType = (sender.tag == 0) ? .phone : .email
self.identityUI = IdentityUI(configuration: .default, identifierType: identifierType)
self.identityUI?.delegate = //...
self.identityUI?.presentIdentityProcess(from: self)
}
@IBAction func didTapLogoutButton(_: Any) {
self.user?.logout()
print("User logout done!")
}
}
To handle the login/signup/error/or any other supported events you can set the IDentityUIDelegate
.
IdentityUIDelegate and UserDelegate
extension ViewController: IdentityUIDelegate {
func didFinish(result: IdentityUIResult) {
switch result {
case .canceled:
print("The user canceled the login process")
case let .completed(user):
self.user = user
self.user.delegate = //...
print("User with id \(String(describing: user.id)) is logged in")
// ... see docs for more cases
}
}
}
extension ViewController: UserDelegate {
func user(_: User, didChangeStateTo newState: UserState) {
switch newState {
case .loggedIn:
print("The user logged in")
case .loggedOut:
print("The user logged out")
}
}
}
UI Customization
The SDK includes an IdentityUITheme
object that allows you to customize the look and feel of the identity UI. See the docs for, hopefully, more details.
Localization
The SDK comes with the following localization support:
- 🇳🇴 Norwegian Bokmål
- 🇸🇪 Swedish
- 🇫🇮 Finnish
Touch ID
Starting from version 2.1.0 of the SDK, and after a first successful password authentication, users can enroll their Touch ID to later use it in a place of entering their password. It is also strongly recommended that users should be able to disable/enable authentication using Touch ID at any time, for which you need to add a UI component (typically a UISwitch
) to your app settings which calls IdentityUIConfiguration.useBiometrics
.
Headless login with IdentityManager
Note: It is recommended to use the UI approach.
The IdentityManager
is more bare bones and doesn't ensure any kind of Schibsted identity flows. It can create a user object and also notify you of any changes that happen to the user object. You can assign an IdentityManagerDelegate
to it to handle various events that take place:
import SchibstedAccount
class ViewController: UIViewController, IdentityManagerDelegate {
let identityManagaer = SchibstedAccount.IdentityManager(clientConfiguration: clientConfiguration)
override func viewDidLoad() {
super.viewDidLoad()
self.identityManager.delegate = self
if self.identityManager.currentUser.state == .loggedIn {
// User is already logged in
return
}
// User not logged in
self.login()
}
func userStateChanged(_ state: UserState) {
// User has just logged in or just logged out
if state == .LoggedIn {
print("User with id \(String(describing: self.identityManager.currentUser.id)) is logged in")
}
}
func login() {
self.identityManager.sendCode(to: PhoneNumber(...) ...) { result in
if case .failure(let error) = result {
print("failed to send code", error)
}
}
}
@IBAction func validateCode(_ sender: UIButton) {
let code = self.codeTextField.text
identityManager.validate(oneTimeCode: code, for: PhoneNumber(...) ...) {
}
}
}
Building, testing, documentaion
See contributing.md.
Github
link |
Stars: 5 |
You may find interesting
Dependencies
Releases
2.9.0 - 2020-11-27T09:54:44
- Support shared web credentials: try to read stored credentials and allow the user to save the credentials to the keychain when logging in. Thanks @clausjoergensen and @vmagaziy
- Upgrade project to Xcode 12. Thanks @clausjoergensen
2.8.1 - 2020-11-17T10:25:40
- Fix deserialisation of legacy storage format for token data. (#316) Thanks to @clausjoergensen
2.8.0 - 2020-10-13T08:02:32
- Replace
SchibstedAccount.Result
withSwift.Result
. Thanks to @clausjoergensen - Allow specifying keychain access group to be able to share authentication between apps on the same Apple team. Thanks to @clausjoergensen
- Add support for Swift Package Manger. Thanks to @clausjoergensen
- Upgrade to Swift 5. Thanks to @mbanasiewicz
- Upgrade deployment target 9.0 -> 11.0. Thanks to @mbanasiewicz
- Allow disabling "What's this" button (to avoid rejection of app since the privacy page leads to a page with subscription purchase possibility). Thanks to @mbanasiewicz
2.7.1 - 2020-06-04T10:33:16
- Don't treat a 400 Bad Request to a refresh request as a logout. (#301)
2.7.0 - 2020-03-20T08:04:28
- Add "show password" toggle. (#291)
2.6.0 - 2020-03-02T15:21:57
- Add helper method for using web flows for login.
- Update age limit according to change in regulation.
2.5.0 - 2019-11-27T12:24:01
- Cleanup expectation in tests. (#270) Thanks to @minarikg 🙇
- Changed: didClick*(: Any) -> didTap*(: UIButton) (#283) Thanks to @minarikg 🙇
- Emit tracking event when the user logs in using biometrics. (#287)
- Changed: remove via SwiftFormat script (#284) Thanks to @minarikg 🙇
- Fix #280: Make login flow modal on iOS 13 if it isn't cancellable. (#288)
2.4.0 - 2019-10-11T11:37:48
-
Bug & security fixes:
- Fix some vulnerable packages in the rubygems dependencies of this project.
-
New features:
- Prefill the user email by default.
- Update Schibsted logo.
2.3.1 - 2019-07-31T13:37:01
No external changes, only internal implementation changes.
2.3.0 - 2019-07-30T14:40:44
- Add support for user login using Face ID.
2.2.0 - 2019-05-13T16:02:11
- Don't call /api/2/logout endpoint on user logout.
2.1.0 - 2019-04-08T11:43:32
Security improvements
- Collect device fingerprint upon user login.
- Add support for user login using Touch ID.
2.0.1 - 2019-02-27T09:21:36
Changed
- Retry network calls also on ECONNABORTED, thanks @salling. (#248)
2.0.0 - 2019-01-22T09:01:03
Added
-
UI: Display a notice message when a new account is created, to prevent users erroneously creating a new account when they believe they are logging-in.
-
Retry network request that fail due to
NSURLErrorNetworkConnectionLost
by @epatel.
Changed
- Moved token refresh retry limit to
SDKConfiguration.refreshRetryCount
(was previouslyUserAuthAPI.refreshRetryCount
).
1.1.0 - 2018-11-16T10:45:40
- The entire area when entering verification codes is now clickable.
1.0.4 - 2018-09-07T12:54:29
- Fixed keychain - when trying to read while app was in background it would break. Much love to @eriksundin.
- Fixed compiler crash on xcode 10.
1.0.1 - 2018-06-29T11:43:17
- Deprecated some bad apples (initializer for IdentityUI)
- Added caching of agreements
- Added support for basic auto fill on username and password for UI login
1.0.0 - 2018-06-22T10:30:57
- Added: email fields to User profile
- Added: allow scopes to be specified during passwordless login
- Changed:
ClientConfiguration
tries best effort to determine environment from serverURL - Fixed: All the tracking
UI
- Added: allow to use default clear text image for text fields
- Added: skip button to UI with delegate to control and new case in
IdentityUIResult
- Changed: make the webview controls match tint colors of icons in theme
- Fixed: styling on 'what's this' button
- Fixed: error popup not applying style
- Fixed: corner radius theming on UI elements
- Fixed: allow scopes during passwordless login flow
- Fixed: custom checkbox image scaling issues
- Fixed forgot password button constraint issue in create user flow
- Fixed: webview transition artifacts on formsheet presentation
- Fixed aborting flow to call the cancel instead of silently exiting
- 2018-05-28T07:56:58
Fixed: call delegate on failure when UI is not started Changed: don't crash if precondition fails in presenting UI
- 2018-05-18T23:57:07
Fixed: Copies Fixed: layout issue with iOS 10 Fixed: Auto layout warnings Fixed: Terms screen on start up Fixed: Issue where user was persisted when terms were not accepted
Added: keyboard dismissal by tapping outside of the text fields
Changed: IdentityUIDelegate didFinish to receive a cancel event when the login process disappears (i.e. when a viewDidDissapear
is called on internal nav stack)
- 2018-05-15T10:37:57
Added: IdentityUI
initializer that does not require an IdentityManager
Added: Independent updated terms screen to show at app startup if required
Added: Loading view when presenting login flow
Added: ability to specify scopes in login
Added: scope propagation through the forgot password flow
Added: can specify additional redirect query items in WebSessionRoutes
Added: sdk type and version headers
Added: presentationHook block to IdentityUIConfiguration called before presenting UI.
Added: sending pulse jwe as additional netwokring headers
Added: ClientError.noAccess
error for product API
Added: Information screen popup
Added: typo on english screen to enter password when creating account
Changed: All screens for initial GDPR compliancy
Changed: removed 8 char password login limit
Changed: detect if a mismatched client configuration is used between IdentityManager
and IdentityUI
Changed: set tracking id as legacy id
Fixed: a number of documentation fixes Fixed: cancel button in terms screen Fixed: error handling in terms screen Fixed: Retain cycle on UI flow the tis already in process Fixed: bug in present update terms logic Fixed: ipad crash for action sheet Fixed: accountSummaryURL web session route Fixed: translations
- 2018-05-08T08:17:56
Fixed: keep user logged in when updating from pre rc release Fixed: password length check for login removed Fixed: retain cycle in UI
- 2018-04-10T13:45:29
Changed: keyboard down by default in UI flows
Changed: tracker protocol to get
a ClientConfiguration
Added: Persistent login on passwordless and password flows
Added: Schibsted branding logo to identifier screen
Added: Custom client logo for identifier screen
Added: Custom teaser text on identifier screen
Added: API to IdentityUIConfiguration
to copy and replace
Fixed: Enter identifier screen spacing Fixed: navigation buttons on flows Fixed: translations Fixed: tests Fixed: Internal networking stubber for offline mode support Fixed: tracking support
Removed: mockingjay dependencies