ursan526
ursan526

Reputation: 535

I can't delete the user logged in with apple

We are implementing the new guidelines imposed by Apple on user deletion. I am using firebase for auth. I am creating a user account. no problem here. but I can't delete users logged in with apple. i am getting error. I am using this api to delete, token revoke API. I'm new to swift. I couldn't find the problem

this is my login code. it's working correct :

class SignUpNewUser: NSObject {
    /// apple
    var currentNonce: String? // fileprivate
}

extension SignUpNewUser : ASAuthorizationControllerPresentationContextProviding{
    
    func Apple() {
        let nonce = randomNonceString()
        currentNonce = nonce
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        let request = appleIDProvider.createRequest()
        request.requestedScopes = [.fullName, .email]
        request.nonce = sha256(nonce)
        
        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.presentationContextProvider = self
        authorizationController.performRequests()
    }
    
    private func sha256(_ input: String) -> String {
        let inputData = Data(input.utf8)
        let hashedData = SHA256.hash(data: inputData)
        let hashString = hashedData.compactMap {
            return String(format: "%02x", $0)
        }.joined()
        
        return hashString
    }
    
    private func randomNonceString(length: Int = 32) -> String {
        precondition(length > 0)
        let charset: Array<Character> =
            Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
        var result = ""
        var remainingLength = length
        
        while remainingLength > 0 {
            let randoms: [UInt8] = (0 ..< 16).map { _ in
                var random: UInt8 = 0
                let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random)
                if errorCode != errSecSuccess {
                    fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)")
                }
                return random
            }
            randoms.forEach { random in
                if length == 0 {
                    return
                }
                
                if random < charset.count {
                    result.append(charset[Int(random)])
                    remainingLength -= 1
                }
            }
        }
        return result
    }
}



extension SignUpNewUser: ASAuthorizationControllerDelegate {
    
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        
        guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else {
            dataSource?.endSignUpWithError(error: eLogin.authorizationNotFound.error(), method: .apple)
            return
        }
        
        guard let nonce = currentNonce else {
            fatalError("Invalid state: A login callback was received, but no login request was sent.")
        }
        
        // JWT
        guard let appleIDToken = appleIDCredential.identityToken else {
            dataSource?.endSignUpWithError(error: eLogin.identityToken.error(), method: .apple)
            return
        }
        
        guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
            mylog(eLogin.serializeToken.error(), appleIDToken.debugDescription)
            dataSource?.endSignUpWithError(error: eLogin.serializeToken.error(), method: .apple)
            return
        }
        
        let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce)
        
        @AppStorage("JWt_client_secret") var client_secret: String = ""
        @AppStorage("apltoken") var apple_token: String = ""
        client_secret = nonce
        apple_token = idTokenString

        signInFirebaseAccount(credential, appleIDCredential:appleIDCredential)
    }
    
    
    
    /// signup tamam firebase bağla hesabı
    private func signInFirebaseAccount(_ credential: AuthCredential, appleIDCredential: ASAuthorizationAppleIDCredential) {
        Auth.auth().signIn(with: credential) { (authResult, error) in
            
            if let error = error {
                self.dataSource?.endSignUpWithError(error: error , method: .apple)
            }else{
                guard let user = authResult?.user else {
                    self.dataSource?.endSignUpWithError(error: eLogin.kayitHatasi.error(), method: .apple)
                    return
                }

                // JWT
                guard let appleIDToken = appleIDCredential.identityToken else {
                    print("hata 5")
                    return
                }
                
                guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
                    print("hata 6")
                    return
                }
                guard let nonce = self.currentNonce else {
                    fatalError("Invalid state: A login callback was received, but no login request was sent.")
                }

                @AppStorage("JWt_client_secret") var client_secret: String = ""
                @AppStorage("apltoken") var apple_token: String = ""
                client_secret = nonce
                apple_token = idTokenString

                
                self.createNewUser(user: user, method: .apple)
                
            }
        }
    }

}

i am using this code to delete account. this is not working. I'm adding the console image I got after running the code.

extension SignUpNewUser{
    func deleteAppleAccount() {
        @AppStorage("JWt_client_secret") var client_secret: String = ""
        @AppStorage("apltoken") var apple_token: String = ""


        let urlString = "https://appleid.apple.com/auth/revoke"
        let url = NSURL(string: urlString)!

        let paramString: [String : Any] = [
            "client_id": "com.MyCompany.Name",
            "client_secret": client_secret,
            "token": apple_token
        ]

        
        let request = NSMutableURLRequest(url: url as URL)
        request.httpMethod = "POST"
        request.httpBody = try? JSONSerialization.data(withJSONObject:paramString, options: [.prettyPrinted])
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
//                request.setValue("application/json", forHTTPHeaderField: "Accept")

        
        let task =  URLSession.shared.dataTask(with: request as URLRequest)  { (data, response, error) in
                guard
                    let response = response as? HTTPURLResponse,
                    error == nil
                else {                                                               // check for fundamental networking error
                    print("error", error ?? URLError(.badServerResponse))
                    return
                }
                
                guard (200 ... 299) ~= response.statusCode else {                    // check for http errors
                    print("statusCode should be 2xx, but is \(response.statusCode)")
                    print("response = \(response)")
                    return
                }

                
            if let error = error {
                print(error)
            }else{
                print("deleted accont")
            }
        }
        task.resume()
    }

}

console output:

statusCode should be 2xx, but is 400
response = <NSHTTPURLResponse: 0x2815e5e00> { URL: https://appleid.apple.com/auth/revoke } { Status Code: 400, Headers {
    "Cache-Control" =     (
        "no-store"
    );
    Connection =     (
        "keep-alive"
    );
    "Content-Length" =     (
        26
    );
    "Content-Type" =     (
        "application/json;charset=ISO-8859-1"
    );
    Date =     (
        "Sat, 28 May 2022 12:07:51 GMT"
    );
    Pragma =     (
        "no-cache"
    );
    Server =     (
        Apple
    );
} }

where am i going wrong? I couldn't find any tutorial about it. Account deletion option will be mandatory after the 30th of the month. I need to fix this now :(

Upvotes: 3

Views: 2163

Answers (1)

Koby
Koby

Reputation: 64

If you don't refresh token users you should try this...

let paramString: [String : Any] = [
            "client_id": "com.MyCompany.Name",
            "client_secret": client_secret,
            "token": apple_token,
            "token_type_hint": "access_token"
        ]

And if you do

let paramString: [String : Any] = [
            "client_id": "com.MyCompany.Name",
            "client_secret": client_secret,
            "token": apple_token,
            "token_type_hint": apple_typeToken

        ]

where apple_typeToken could be "access_token" or "refresh_token"

And you should edit your request.httpMethod like

HTTP Request in Swift with POST method

Upvotes: 1

Related Questions