user20121009
user20121009

Reputation:

How to authenticate the Api with JWT in Swiftui?

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

Answers (1)

Anup Kumar Mishra
Anup Kumar Mishra

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

Related Questions