Reputation:
I want to try the authentication web service using JSON Web Tokens (JWTs) — that includes both client-side, and server-side code. and trying to fetch the access_token but I can't get the authentication even username and password is correct.
This is Login View and I enter the valid username and password:
struct LoginViewExample: View {
@State var email = ""
@State var password = ""
// @State var isAuthenticated: Bool = false
@StateObject private var loginVM = DashBoardLoginViewModel()
var body: some View {
NavigationView{
VStack() {
Text("Welcome!")
.font(.title)
VStack(alignment: .leading, spacing: 15) {
TextField("Username", text: $loginVM.username)
.autocapitalization(.none)
.disableAutocorrection(true)
.padding()
SecureField("Password", text: $loginVM.password)
.textContentType(.password)
.padding()
}
.padding([.leading, .trailing], 50)
Button(action: {
loginVM.login()
}) {
Text("Sign In")
.font(.headline)
.foregroundColor(.white)
.padding()
}.padding(.top, 50)
}
.background(
LinearGradient(gradient: Gradient(colors: [Color.yellow, Color.green]), startPoint: .top, endPoint: .bottom)
.edgesIgnoringSafeArea(.all))
}
}
}
This is struct Auth Body Model
struct LoginRequestBodyAuth: Codable {
let username: String
let password: String
}
struct LoginAuthResponse: Codable {
let access_token: String? // this is access token key
}
class DashBoardLoginViewModel: ObservableObject {
@Published var isAuthenticated: Bool = false
var username: String = "8299544315" //this is valid username
var password: String = "12345678" //this is password
func login() {
let defaults = UserDefaults.standard
AuthenticationService().login(username: username, password: password) { result in
switch result {
case .success(let token):
defaults.setValue(token, forKey: "access_token")
DispatchQueue.main.async {
self.isAuthenticated = true
print(token)
}
case .failure(let error):
print(error.localizedDescription) //this prints every time
}
}
}
}
}
This is Web service here I set the body and header. And don't understand where I am doing wrong. please correct me where I am wrong. this is my full approach.
class AuthenticationService {
func login(username: String, password: String, completion: @escaping (Result<String, AuthenticationError>) -> Void) {
guard let url = URL(string: "example url") else {
completion(.failure(.custom(errorMessage: "URL is not correct")))
return
}
let body = LoginRequestBodyAuth(username: username, password: password)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONEncoder().encode(body)
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
completion(.failure(.custom(errorMessage: "No data")))
return
}
try? JSONDecoder().decode(LoginAuthResponse.self, from: data)
guard let loginResponse = try? JSONDecoder().decode(LoginAuthResponse.self, from: data) else {
completion(.failure(.invalidCredentials))
return
}
guard let token = loginResponse.access_token else {
completion(.failure(.invalidCredentials))
return
}
completion(.success(token))
}.resume()
}
}
Upvotes: 0
Views: 1581
Reputation: 206
Please Add the logout_consent for if u want to get the access if anyone is logged in. do this Approach. In my case this is working.
struct LoginRequestBodyAuth: Codable {
let email: String
let password: String
let logout_consent:String
}
and some changes in Your AuthenticationService Class
class AuthenticationService {
func login(username: String, password: String,completion: @escaping (Result<String, AuthenticationError>) -> Void) {
guard let url = URL(string: "urlExample") else {
completion(.failure(.custom(errorMessage: "URL is not correct")))
return
}
let body = LoginRequestBodyAuth(email: username, password: password, logout_consent: "1")
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONEncoder().encode(body)
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
completion(.failure(.custom(errorMessage: "No data")))
return
}
guard let loginResponse = try? JSONDecoder().decode(LoginAuthResponse.self, from: data) else {
completion(.failure(.invalidCredentials))
return
}
// print(loginResponse)
guard let token = loginResponse.access_token else {
completion(.failure(.invalidCredentials))
return
}
completion(.success(token))
}.resume()
}
}
Upvotes: 0