77
88import Foundation
99
10- @available ( iOS 13 . 0 , * )
1110internal final class UID2Client {
1211
1312 private let uid2APIURL : String
@@ -16,56 +15,75 @@ internal final class UID2Client {
1615
1716 init ( uid2APIURL: String , sdkVersion: String , _ session: NetworkSession = URLSession . shared) {
1817 self . uid2APIURL = uid2APIURL
18+ #if os(tvOS)
19+ self . clientVersion = " tvos- \( sdkVersion) "
20+ #else
1921 self . clientVersion = " ios- \( sdkVersion) "
22+ #endif
2023 self . session = session
2124 }
2225
2326 func refreshIdentity( refreshToken: String , refreshResponseKey: String ) async throws -> RefreshAPIPackage {
2427
25- var components = URLComponents ( string: uid2APIURL)
26- components? . path = " /v2/token/refresh "
27-
28- guard let urlPath = components? . url? . absoluteString,
29- let url = URL ( string: urlPath) else {
30- throw UID2Error . urlGeneration
31- }
32-
33- var request = URLRequest ( url: url)
34- request. httpMethod = " POST "
35- request. addValue ( clientVersion, forHTTPHeaderField: " X-UID2-Client-Version " )
36- request. addValue ( " application/x-www-form-urlencoded " , forHTTPHeaderField: " Content-Type " )
37- request. httpBody = refreshToken. data ( using: . utf8)
38-
39- let dataResponse = try await session. loadData ( for: request)
40- let data = dataResponse. 0
41- let statusCode = dataResponse. 1
42-
43- let decoder = JSONDecoder ( )
44- decoder. keyDecodingStrategy = . convertFromSnakeCase
45-
46- // Only Decrypt If HTTP Status is 200 (Success or Opt Out)
47- if statusCode != 200 {
48- do {
49- let tokenResponse = try decoder. decode ( RefreshTokenResponse . self, from: data)
50- throw UID2Error . refreshTokenServer ( status: tokenResponse. status, message: tokenResponse. message)
51- } catch {
52- throw UID2Error . refreshTokenServerDecoding ( httpStatus: statusCode, message: error. localizedDescription)
53- }
54- }
55-
56- // Decrypt Data Envelop
57- // https://github.com/UnifiedID2/uid2docs/blob/main/api/v2/encryption-decryption.md
58- guard let payloadData = DataEnvelope . decrypt ( refreshResponseKey, data, true ) else {
59- throw UID2Error . decryptPayloadData
60- }
61-
62- let tokenResponse = try decoder. decode ( RefreshTokenResponse . self, from: payloadData)
63-
64- guard let refreshAPIPackage = tokenResponse. toRefreshAPIPackage ( ) else {
65- throw UID2Error . refreshResponseToRefreshAPIPackage
28+ let request = Request . refresh ( token: refreshToken)
29+ let ( data, statusCode) = try await execute ( request)
30+
31+ let decoder = JSONDecoder ( )
32+ decoder. keyDecodingStrategy = . convertFromSnakeCase
33+
34+ // Only Decrypt If HTTP Status is 200 (Success or Opt Out)
35+ if statusCode != 200 {
36+ do {
37+ let tokenResponse = try decoder. decode ( RefreshTokenResponse . self, from: data)
38+ throw UID2Error . refreshTokenServer ( status: tokenResponse. status, message: tokenResponse. message)
39+ } catch {
40+ throw UID2Error . refreshTokenServerDecoding ( httpStatus: statusCode, message: error. localizedDescription)
6641 }
67-
68- return refreshAPIPackage
6942 }
7043
44+ // Decrypt Data Envelop
45+ // https://github.com/UnifiedID2/uid2docs/blob/main/api/v2/encryption-decryption.md
46+ guard let payloadData = DataEnvelope . decrypt ( refreshResponseKey, data, true ) else {
47+ throw UID2Error . decryptPayloadData
48+ }
49+
50+ let tokenResponse = try decoder. decode ( RefreshTokenResponse . self, from: payloadData)
51+
52+ guard let refreshAPIPackage = tokenResponse. toRefreshAPIPackage ( ) else {
53+ throw UID2Error . refreshResponseToRefreshAPIPackage
54+ }
55+
56+ return refreshAPIPackage
57+ }
58+
59+ // MARK: - Request Execution
60+
61+ internal func urlRequest(
62+ _ request: Request ,
63+ baseURL: URL
64+ ) -> URLRequest {
65+ var urlComponents = URLComponents ( url: baseURL, resolvingAgainstBaseURL: true ) !
66+ urlComponents. path = request. path
67+ urlComponents. queryItems = request. queryItems. isEmpty ? nil : request. queryItems
68+
69+ var urlRequest = URLRequest ( url: urlComponents. url!)
70+ urlRequest. httpMethod = request. method. rawValue
71+ if request. method == . post {
72+ urlRequest. httpBody = request. body
73+ }
74+
75+ request. headers. forEach { field, value in
76+ urlRequest. addValue ( value, forHTTPHeaderField: field)
77+ }
78+ urlRequest. addValue ( clientVersion, forHTTPHeaderField: " X-UID2-Client-Version " )
79+ return urlRequest
80+ }
81+
82+ private func execute( _ request: Request ) async throws -> ( Data , Int ) {
83+ let urlRequest = urlRequest (
84+ request,
85+ baseURL: URL ( string: uid2APIURL) !
86+ )
87+ return try await session. loadData ( for: urlRequest)
88+ }
7189}
0 commit comments