-
Notifications
You must be signed in to change notification settings - Fork 111
/
Copy pathAuthScheme.swift
101 lines (88 loc) · 3.4 KB
/
AuthScheme.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//
// AuthScheme.swift
// ios
//
// Copyright © 2019 Tinode. All rights reserved.
//
import Foundation
public struct AuthScheme {
enum AuthSchemeError: Error {
case invalidParams(String)
}
static let kLoginBasic = "basic"
static let kLoginToken = "token"
static let kLoginReset = "reset"
static let kLoginCode = "code"
let scheme: String
let secret: String
init(scheme: String, secret: String) {
self.scheme = scheme
self.secret = secret
}
static func parse(from str: String?) throws -> AuthScheme? {
if let data = str {
let parts = data.split(separator: ":")
if parts.count == 2 {
let scheme = String(parts[0])
if scheme == kLoginBasic || scheme == kLoginToken {
return AuthScheme(scheme: scheme, secret: String(parts[1]))
}
} else {
throw AuthSchemeError.invalidParams("Invalid param string \(data)")
}
}
return nil
}
static func encodeBasicToken(uname: String, password: String) throws -> String {
guard !uname.contains(":") else {
throw AuthSchemeError.invalidParams("invalid user name: \(uname)")
}
return (uname + ":" + password).toBase64()!
}
static func encodeResetToken(scheme: String, method: String, value: String) throws -> String {
guard !scheme.contains(":") && !method.contains(":") else {
throw AuthSchemeError.invalidParams("invalid parameter")
}
return "\(scheme):\(method):\(value)".toBase64()!
}
static func decodeBasicToken(token: String) throws -> [String] {
guard let basicToken = token.fromBase64() else {
throw AuthSchemeError.invalidParams(
"Failed to decode auth token from base64: \(token)")
}
let parts = basicToken.split(separator: ":")
if parts.count != 2 || parts[0].isEmpty {
throw AuthSchemeError.invalidParams(
"Invalid basic token string: \(basicToken)")
}
return [String(parts[0]), String(parts[1])]
}
static func basicInstance(login: String, password: String) throws -> AuthScheme {
return AuthScheme(scheme: kLoginBasic,
secret: try encodeBasicToken(uname: login, password: password))
}
static func tokenInstance(secret: String) -> AuthScheme {
return AuthScheme(scheme: kLoginToken, secret: secret)
}
public static func codeInstance(code: String, method: String, value: String) throws -> AuthScheme {
// The secret is structured as <code>:<cred_method>:<cred_value>, "123456:email:[email protected]".
return AuthScheme(scheme: AuthScheme.kLoginCode, secret: try encodeResetToken(scheme: code, method: method, value: value))
}
}
extension String {
func fromBase64() -> String? {
guard let data = Data(base64Encoded: self,
options: Data.Base64DecodingOptions(
rawValue: 0)) else {
return nil
}
return String(data: data as Data, encoding: String.Encoding.utf8)
}
func toBase64() -> String? {
guard let data = self.data(using: String.Encoding.utf8) else {
return nil
}
return data.base64EncodedString(
options: Data.Base64EncodingOptions(rawValue: 0))
}
}