Building Spotify App in Swift 5 & UIKit - Sign In Wrap Up (Xcode 12, 2022, Swift 5) - Build App
AuthManager
: 스포티파이 인증 사용되는 URLRequest 정보의 쿼리 정보를 통해 토큰 값 저장 func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
guard let url = webView.url else {
return }
// Exchange the code for access token
guard let code = URLComponents(string: url.absoluteString)?.queryItems?.first(where: {$0.name == "code"})?.value else {
return
}
webView.isHidden = true
print("Code: \(code)")
AuthManager.shared.exchangeCodeForToken(code: code) { [weak self] success in
guard let self = self else { return }
DispatchQueue.main.async {
self.navigationController?.popToRootViewController(animated: true)
self.completionHandler?(success)
}
}
}
AuthManager
에서 해당 값을 유저 디폴트로 저장하기 위한 비동기적 데이터 전달 public func exchangeCodeForToken(code: String, completionHandler: @escaping (Bool) -> ()) {
// GET TOKEN
guard let url = URL(string: Constants.tokenAPIURLString) else { return }
var components = URLComponents()
components.queryItems = [
URLQueryItem(name: "grant_type", value: "authorization_code"),
URLQueryItem(name: "code", value: code),
URLQueryItem(name: "redirect_uri", value: Constants.redirectURI),
]
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let basicToken = Constants.clientID + ":" + Constants.clientSecret
let data = basicToken.data(using: .utf8)
guard let base64String = data?.base64EncodedString() else {
completionHandler(false)
return
}
urlRequest.setValue("Basic \(base64String)", forHTTPHeaderField: "Authorization")
urlRequest.httpBody = components.query?.data(using: .utf8)
URLSession.shared.dataTask(with: urlRequest) { [weak self] data, response, error in
guard let self = self else { return }
if let error = error {
print(error.localizedDescription)
completionHandler(false)
return
} else if let data = data {
do {
let result = try JSONDecoder().decode(AuthResponse.self, from: data)
print("SUCCESSFULLY REFRESH")
self.cacheToken(result: result)
completionHandler(true)
} catch {
print(error.localizedDescription)
completionHandler(false)
}
}
}
.resume()
}
grant_type
, code
, redirect_uri
) 등을 받아오기 위한 POST
AuthResponse
데이터 모델을 API를 통해 리턴struct AuthResponse: Codable {
let access_token: String
let expires_in: Int
let refresh_token: String?
let scope: String
let token_type: String
}
URL 부분 문자가 틀리면 곧바로 다르게 인식되기 때문에 복사/붙여넣기를 통해 접근하자...!