Estou criando um aplicativo de bate-papo em Swift usando URLSession
. Tenho uma solicitação GET autenticada para buscar a lista de amigos do usuário atual. A solicitação funciona perfeitamente no Postman usando o mesmo token e URL, mas meu aplicativo iOS retorna consistentemente um erro 403 com { "detail": "Not Authenticated" }
.
O que eu tentei :
- Garantiu que o cabeçalho de autorização está incluído (
Bearer <token>
) - Registrei a URL completa e o token — eles estão corretos!
- Verifiquei se o servidor de backend está acessível (consigo fazer POST com sucesso)
- Confirmado que a mesma solicitação GET com token funciona bem no Postman
- HTTP inseguro permitido em
Info.plist
(servidor éhttp://52.23.164.179:8000
)
Meu código :
ContactListVC.swift :
private func fetchContacts() {
ContactService.shared.getFriends { [weak self] success, contacts in
guard let self = self else { return }
DispatchQueue.main.async {
if success, let contacts = contacts, !contacts.isEmpty {
self.contacts = contacts
self.tableView.reloadData()
} else {
self.contacts = []
self.showEmptyStateIfNeeded()
}
}
}
}
ContactService.swift :
func getFriends(completion: @escaping (Bool, [ChatPartner]?) -> Void) {
guard let request = contactRequest.getFriends() else {
completion(false, nil)
return
}
NetworkService.shared.sendRequest(request, parse: { data in
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let dataObject = json["data"] as? [String: Any],
let friendsArray = dataObject["friends"] as? [[String: Any]] else {
return nil
}
return friendsArray.compactMap { ChatPartner(json: $0) }
}) { result in
switch result {
case .success(let partners):
completion(true, partners)
case .failure:
completion(false, nil)
}
}
}
ContactRequest.swift :
func getFriends() -> URLRequest? {
guard let baseURL = BASE_URL else { return nil }
let url = baseURL.appendingPathComponent("friends")
var request = URLRequest(url: url)
request.setValue("Bearer \(token ?? "")", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
return request
}
Serviço de rede.swift :
func sendRequest<T>(_ request: URLRequest, parse: @escaping (Data) -> T?, completion: @escaping (Result<T, NetworkError>) -> Void) {
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let httpResponse = response as? HTTPURLResponse, let data = data else {
completion(.failure(.invalidResponse))
return
}
switch httpResponse.statusCode {
case 200:
if let result = parse(data) {
completion(.success(result))
} else {
completion(.failure(.parsingFailed))
}
default:
completion(.failure(.statusCode(httpResponse.statusCode)))
}
}
task.resume()
}
Info.plist :
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>52.23.164.179</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Questões :
- Por que estou recebendo uma resposta 403 no iOS, mas não no Postman com o mesmo token?
- É possível que alguns cabeçalhos ausentes (por exemplo, User-Agent) façam com que a API o rejeite?
Observações extras :
- Confirmei que a solicitação inclui o
Authorization
cabeçalho registrando-o. - Estou usando um endereço IP local (não HTTPS).
- O token não expirou (verificado no Postman).
- Aqui estão algumas imagens quando depuro: