I've retrieved the username and password from a UITextField
and now I want to set the username and password to every request Moya performs with basic auth.
How do I do this?
I've retrieved the username and password from a UITextField
and now I want to set the username and password to every request Moya performs with basic auth.
How do I do this?
The documentation that covers Basic Authentication is here
Here are the required parts you need
HTTP auth is a username/password challenge built into the HTTP protocol itself. If you need to use HTTP auth, you can provide a CredentialsPlugin when initializing your provider.
let provider = MoyaProvider<YourAPI>(plugins: [CredentialsPlugin { _ -> URLCredential? in
return URLCredential(user: "user", password: "passwd", persistence: .none)
}
])
This specific examples shows a use of HTTP that authenticates every request, which is usually not necessary. This might be a better idea:
let provider = MoyaProvider<YourAPI>(plugins: [CredentialsPlugin { target -> URLCredential? in
switch target {
case .targetThatNeedsAuthentication:
return URLCredential(user: "user", password: "passwd", persistence: .none)
default:
return nil
}
}
])
This solution don't work for me.
The problem is that the URLCredential
is only used for authentication challenges, not for preauthorizing the request. So if your API requires an Authorization header with Base64 "username:password" param this won't work. There seems to be a lot of confusion around how this works, see this similar issue on Alamofire.
I worked around this with the following:
SOLUTION 1
lazy var provider: MoyaProvider<LoginService> = {
let endpointClosure = { (target: LoginService) -> Endpoint<LoginService> in
let defaultEndpoint = MoyaProvider.defaultEndpointMapping(for: target)
switch target {
case .login(let username, let password):
return defaultEndpoint.adding(newHTTPHeaderFields: ["Authorization": "Basic " + "\(username):\(password)".data(using: .nonLossyASCII)!.base64EncodedString(options: []))
}
}
return MoyaProvider(endpointClosure: endpointClosure)
}()
Here is other solution with Moya Plugin approach:
SOLUTION 2
class AuthProvider {
static let basicAuthPlugin: PluginType = AccessTokenPlugin(tokenClosure: { () -> String in
guard let loginData = String(format: "\("username"):\("password")").data(using: .utf8) else { return "" }
return loginData.base64EncodedString()
})
}
let AuthAPIProvider = MoyaProvider<AuthAPI>(plugins: [AuthProvider.basicAuthPlugin])
enum AuthAPI {
// ... methods
}
extension AuthAPI: AccessTokenAuthorizable {
var authorizationType: AuthorizationType {
return .basic
}
}