Update auth documentation
This commit is contained in:
parent
9df955bebc
commit
50e30153bc
|
@ -11,9 +11,9 @@ import Foundation
|
||||||
/**
|
/**
|
||||||
This struct represents a unique authentication.
|
This struct represents a unique authentication.
|
||||||
|
|
||||||
This struct currently only has an `id` but it is still used
|
This struct currently only has an `id` but is still used to
|
||||||
to be able to extend the authentication information without
|
be able to extend the authentication info without having to
|
||||||
having to change any authentication protocols.
|
change any authentication protocols.
|
||||||
*/
|
*/
|
||||||
public struct Authentication {
|
public struct Authentication {
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ public protocol AuthenticationService: AnyObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Authenticate the user for a certain authentication type.
|
Authenticate the user for a certain authentication type.
|
||||||
`reason` can be used as display information to the user.
|
|
||||||
|
`reason` can be used to display information to the user.
|
||||||
*/
|
*/
|
||||||
func authenticateUser(for auth: Authentication, reason: String, completion: @escaping AuthCompletion)
|
func authenticateUser(for auth: Authentication, reason: String, completion: @escaping AuthCompletion)
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,13 @@ public class BiometricAuthenticationService: AuthenticationService {
|
||||||
|
|
||||||
// MARK: - Public functions
|
// MARK: - Public functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
Authenticate the user for a certain authentication type,
|
||||||
|
provided that the service can authenticate the user for
|
||||||
|
the provided authentication type.
|
||||||
|
|
||||||
|
`reason` can be used to display information to the user.
|
||||||
|
*/
|
||||||
public func authenticateUser(for auth: Authentication, reason: String, completion: @escaping AuthCompletion) {
|
public func authenticateUser(for auth: Authentication, reason: String, completion: @escaping AuthCompletion) {
|
||||||
guard canAuthenticateUser(for: auth) else { return completion(.failure(AuthError.unsupportedAuthentication)) }
|
guard canAuthenticateUser(for: auth) else { return completion(.failure(AuthError.unsupportedAuthentication)) }
|
||||||
performAuthentication(for: auth, reason: reason) { result in
|
performAuthentication(for: auth, reason: reason) { result in
|
||||||
|
@ -36,11 +43,23 @@ public class BiometricAuthenticationService: AuthenticationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if the service instance can authenticate the user
|
||||||
|
for a certain authentication type.
|
||||||
|
*/
|
||||||
public func canAuthenticateUser(for auth: Authentication) -> Bool {
|
public func canAuthenticateUser(for auth: Authentication) -> Bool {
|
||||||
var error: NSError?
|
var error: NSError?
|
||||||
return LAContext().canEvaluatePolicy(policy, error: &error)
|
return LAContext().canEvaluatePolicy(policy, error: &error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Authenticate the user for a certain authentication type,
|
||||||
|
regardless of if this service can authenticate the user
|
||||||
|
for the provided authentication type or not.
|
||||||
|
|
||||||
|
This is a way to bypass any particular rules and states
|
||||||
|
of the service and is not part of the service protocol.
|
||||||
|
*/
|
||||||
public func performAuthentication(for auth: Authentication, reason: String, completion: @escaping AuthCompletion) {
|
public func performAuthentication(for auth: Authentication, reason: String, completion: @escaping AuthCompletion) {
|
||||||
LAContext().evaluatePolicy(policy, localizedReason: reason) { result, error in
|
LAContext().evaluatePolicy(policy, localizedReason: reason) { result, error in
|
||||||
if let error = error { return completion(.failure(error)) }
|
if let error = error { return completion(.failure(error)) }
|
||||||
|
|
|
@ -18,7 +18,7 @@ import Foundation
|
||||||
to perform biometric authentication to access critical data.
|
to perform biometric authentication to access critical data.
|
||||||
|
|
||||||
Note that you can't rely on a cached authentication service
|
Note that you can't rely on a cached authentication service
|
||||||
to clear its cached state. Call `resetUserAuthentication()`
|
to clear its cached state. Call `resetUserAuthentications()`
|
||||||
or `resetUserAuthentication(for:)` as soon as this state is
|
or `resetUserAuthentication(for:)` as soon as this state is
|
||||||
considered to be invalid, e.g. when your app is send to the
|
considered to be invalid, e.g. when your app is send to the
|
||||||
background and a new user can open the app at a later time.
|
background and a new user can open the app at a later time.
|
||||||
|
@ -26,19 +26,20 @@ import Foundation
|
||||||
public protocol CachedAuthenticationService: AuthenticationService {
|
public protocol CachedAuthenticationService: AuthenticationService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if the user has already been authenticated for an
|
Check if the service has already authenticated the user
|
||||||
authentication type.
|
for a certain authentication type.
|
||||||
*/
|
*/
|
||||||
func isUserAuthenticated(for auth: Authentication) -> Bool
|
func isUserAuthenticated(for auth: Authentication) -> Bool
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset the user's entire authentication state.
|
Reset the service's cached authentication state for the
|
||||||
*/
|
provided authentication type.
|
||||||
func resetUserAuthentication()
|
|
||||||
|
|
||||||
/**
|
|
||||||
Reset the user's authentication state for a single type
|
|
||||||
of authentication.
|
|
||||||
*/
|
*/
|
||||||
func resetUserAuthentication(for auth: Authentication)
|
func resetUserAuthentication(for auth: Authentication)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the service's cached authentication state for all
|
||||||
|
authentication types.
|
||||||
|
*/
|
||||||
|
func resetUserAuthentications()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,7 @@ import Foundation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This service wraps another authentication service and keeps
|
This service wraps another authentication service and keeps
|
||||||
authentication results in a cache. `resetUserAuthentication`
|
authentication results in a cache.
|
||||||
can be called to clear one or all caches and force users to
|
|
||||||
perform new authentications to , e.g. after sending the app
|
|
||||||
to the background.
|
|
||||||
*/
|
*/
|
||||||
public class CachedAuthenticationServiceProxy: CachedAuthenticationService {
|
public class CachedAuthenticationServiceProxy: CachedAuthenticationService {
|
||||||
|
|
||||||
|
@ -34,6 +31,11 @@ public class CachedAuthenticationServiceProxy: CachedAuthenticationService {
|
||||||
|
|
||||||
// MARK: - Functions
|
// MARK: - Functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
Authenticate the user for a certain authentication type.
|
||||||
|
|
||||||
|
`reason` can be used to display information to the user.
|
||||||
|
*/
|
||||||
public func authenticateUser(for auth: Authentication, reason: String, completion: @escaping AuthCompletion) {
|
public func authenticateUser(for auth: Authentication, reason: String, completion: @escaping AuthCompletion) {
|
||||||
if isUserAuthenticated(for: auth) { return completion(.success(())) }
|
if isUserAuthenticated(for: auth) { return completion(.success(())) }
|
||||||
baseService.authenticateUser(for: auth, reason: reason) { result in
|
baseService.authenticateUser(for: auth, reason: reason) { result in
|
||||||
|
@ -42,21 +44,37 @@ public class CachedAuthenticationServiceProxy: CachedAuthenticationService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if the service instance can authenticate the user
|
||||||
|
for a certain authentication type.
|
||||||
|
*/
|
||||||
public func canAuthenticateUser(for auth: Authentication) -> Bool {
|
public func canAuthenticateUser(for auth: Authentication) -> Bool {
|
||||||
baseService.canAuthenticateUser(for: auth)
|
baseService.canAuthenticateUser(for: auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if the service has already authenticated the user
|
||||||
|
for a certain authentication type.
|
||||||
|
*/
|
||||||
public func isUserAuthenticated(for auth: Authentication) -> Bool {
|
public func isUserAuthenticated(for auth: Authentication) -> Bool {
|
||||||
cache[auth.id] ?? false
|
cache[auth.id] ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
public func resetUserAuthentication() {
|
/**
|
||||||
cache.removeAll()
|
Reset the service's cached authentication state for the
|
||||||
}
|
provided authentication type.
|
||||||
|
*/
|
||||||
public func resetUserAuthentication(for auth: Authentication) {
|
public func resetUserAuthentication(for auth: Authentication) {
|
||||||
setIsAuthenticated(false, for: auth)
|
setIsAuthenticated(false, for: auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the service's cached authentication state for all
|
||||||
|
authentication types.
|
||||||
|
*/
|
||||||
|
public func resetUserAuthentications() {
|
||||||
|
cache.removeAll()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ class CachedAuthenticationServiceProxyTests: QuickSpec {
|
||||||
service.authenticateUser(for: auth, reason: "") { _ in
|
service.authenticateUser(for: auth, reason: "") { _ in
|
||||||
expect(service.isUserAuthenticated(for: .standard)).to(beTrue())
|
expect(service.isUserAuthenticated(for: .standard)).to(beTrue())
|
||||||
expect(service.isUserAuthenticated(for: auth)).to(beTrue())
|
expect(service.isUserAuthenticated(for: auth)).to(beTrue())
|
||||||
service.resetUserAuthentication()
|
service.resetUserAuthentications()
|
||||||
expect(service.isUserAuthenticated(for: .standard)).to(beFalse())
|
expect(service.isUserAuthenticated(for: .standard)).to(beFalse())
|
||||||
expect(service.isUserAuthenticated(for: auth)).to(beFalse())
|
expect(service.isUserAuthenticated(for: auth)).to(beFalse())
|
||||||
asyncTrigger.trigger()
|
asyncTrigger.trigger()
|
||||||
|
|
Loading…
Reference in New Issue