From db51aa3ac4c03142f07e0ced6695484700e6de7e Mon Sep 17 00:00:00 2001 From: biaduque Date: Thu, 31 Jul 2025 14:21:29 -0300 Subject: [PATCH] feat: add auth with token meli --- .gitignore | 2 - .../Modules/Features/1. Home/HomeRouter.swift | 1 - .../Features/1. Home/HomeViewController.swift | 20 +++- MeliProject/Modules/Token/AuthManager.swift | 95 +++++++++++++++++++ MeliProject/Modules/Token/TokenManager.swift | 18 ++++ 5 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 MeliProject/Modules/Token/AuthManager.swift create mode 100644 MeliProject/Modules/Token/TokenManager.swift diff --git a/.gitignore b/.gitignore index 3b9834a..185e766 100644 --- a/.gitignore +++ b/.gitignore @@ -51,5 +51,3 @@ fastlane/test_output/ timeline.xctimeline playground.xcworkspace - -**/Token/ \ No newline at end of file diff --git a/MeliProject/Modules/Features/1. Home/HomeRouter.swift b/MeliProject/Modules/Features/1. Home/HomeRouter.swift index 53b907c..4f6e92a 100644 --- a/MeliProject/Modules/Features/1. Home/HomeRouter.swift +++ b/MeliProject/Modules/Features/1. Home/HomeRouter.swift @@ -5,7 +5,6 @@ // Created by Beatriz Duque on 28/07/25. // -// TO-DO: adicionar modelo para detalhe protocol HomeRoutingProtocol: AnyObject { func goToDetail(from id: String) } diff --git a/MeliProject/Modules/Features/1. Home/HomeViewController.swift b/MeliProject/Modules/Features/1. Home/HomeViewController.swift index f0a0f36..2aa41c9 100644 --- a/MeliProject/Modules/Features/1. Home/HomeViewController.swift +++ b/MeliProject/Modules/Features/1. Home/HomeViewController.swift @@ -66,10 +66,22 @@ class HomeViewController: UIViewController { func setupController() { styleView?.setup(delegate: self) -// if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate { -// sceneDelegate.authCoordinator?.startMercadoLivreAuth() -// } - } + ///WIP + /// authenticateMeli() + } + + // MARK: TO-DO + /// WIP + /// Chama autenticação do usuário via login no MELI pelo browser + /// Funcionalidade ainda nao implementada e homologada + /** + func authenticateMeli() { + if let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate { + sceneDelegate.authCoordinator?.startMercadoLivreAuth() + } + } + */ + } // MARK: Presenter functions diff --git a/MeliProject/Modules/Token/AuthManager.swift b/MeliProject/Modules/Token/AuthManager.swift new file mode 100644 index 0000000..a92ab7a --- /dev/null +++ b/MeliProject/Modules/Token/AuthManager.swift @@ -0,0 +1,95 @@ +// +// AuthManager.swift +// MeliProject +// +// Created by Beatriz Duque on 29/07/25. +// + +import Foundation +import AuthenticationServices + +// MARK: WIP - classe deve ser melhorada para orquestração, atualização e armazenamento seguro do token +class AuthManager: NSObject, ASWebAuthenticationPresentationContextProviding { + + // MARK: - Propriedades de Configuração + let clientID: String = TokenManager.clientID + let redirectURI: String = TokenManager.redirectURI + let clientSecret: String = TokenManager.secret + + // MARK: - Propriedades de Instância + private var webAuthSession: ASWebAuthenticationSession? + private let apiManager: MeliAPIManagerProtocol + + // Inicializador + init(apiManager: MeliAPIManagerProtocol) { + self.apiManager = apiManager + super.init() + } + + // MARK: - Autenticação com Mercado Livre (Fluxo OAuth 2.0) + + /// 1. Construir a URL de autorização do Mercado Livre + /// 2. Iniciar a sessão de autenticação web + /// 3. Trocar o código de autorização por um token de acesso + func startMercadoLivreAuth() { + guard var authComponents = URLComponents(string: "https://auth.mercadolivre.com.br/authorization") else { return } + authComponents.queryItems = [ + URLQueryItem(name: "response_type", value: "code"), + URLQueryItem(name: "client_id", value: clientID), + URLQueryItem(name: "redirect_uri", value: redirectURI), + URLQueryItem(name: "scope", value: "read_profile write_items") + ] + + guard let authURL = authComponents.url else { return } + + webAuthSession = ASWebAuthenticationSession(url: authURL, callbackURLScheme: URL(string: redirectURI)?.scheme) { [weak self] callbackURL, error in + guard let self = self else { return } + + if let error = error { + FirebaseManager.shared.errorReport(error: error, "erro-na-autenticacao-web") + return + } + + guard let callbackURL = callbackURL, + let urlComponents = URLComponents(url: callbackURL, resolvingAgainstBaseURL: true), + let code = urlComponents.queryItems?.first(where: { $0.name == "code" })?.value else { + FirebaseManager.shared.errorReport(error: MeliAPIError.invalidURL, "url-de-callback-inválida-ou-codigo-nao-encontrado") + return + } + + /// TO-DO: Melhoria: redirectURI ser uma API do backend, + /// que então fará a requisição com o client_secret para o Mercado Livre. + Task { + do { + let tokenResponse = try await self.apiManager.requestAccessToken( + code: code, + clientID: self.clientID, + clientSecret: self.clientSecret, + redirectURI: self.redirectURI + ) + + // TO-DO: Armazenar o token de forma segura (ex: Keychain) + // self.saveTokensToKeychain(accessToken: tokenResponse.accessToken, refreshToken: tokenResponse.refreshToken) + + self.apiManager.updateAccessToken(tokenResponse.accessToken) + } catch { + /// TO-DO: Lidar com o erro de rede/API + FirebaseManager.shared.errorReport(error: error, "erro-ao-trocar-codigo-por-token") + } + } + } + + webAuthSession?.presentationContextProvider = self + webAuthSession?.prefersEphemeralWebBrowserSession = true // Para não persistir cookies de login + webAuthSession?.start() + } + + // MARK: - ASWebAuthenticationPresentationContextProviding + func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { + if let windowScene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene, + let window = windowScene.windows.first { + return window + } + return ASPresentationAnchor() + } +} diff --git a/MeliProject/Modules/Token/TokenManager.swift b/MeliProject/Modules/Token/TokenManager.swift new file mode 100644 index 0000000..8361873 --- /dev/null +++ b/MeliProject/Modules/Token/TokenManager.swift @@ -0,0 +1,18 @@ +// +// TokenManager.swift +// MeliProject +// +// Created by Beatriz Duque on 28/07/25. +// + +/** + *WIP* + Implementação do token em andamento + Necessário para acessar consultas de API do Meli + **/ +struct TokenManager { + static let clientID = "" + static let redirectURI = "meliappcallback://callback" + static var secret = "" + static var value = "" +}