EEYatHo 앱 깎는 이야기

Swift ) 애플로그인 2번째 이후 이메일 - EEYatHo iOS 본문

iOS, Swift

Swift ) 애플로그인 2번째 이후 이메일 - EEYatHo iOS

EEYatHo 2021. 10. 5. 13:51
반응형

 

 

언제부턴가 막혀서

해당 꼼수로 email 받아올 수 없게 되었따..

 

 

 


 

 

애플로그인시 해당 함수로 콜백되며, email을 포함한 각종 유저 정보를 얻을 수 있다.

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
    
    guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else {
        return
    }

    let email = credential.email
    let user = credential.user
    var authCode = ""
    if let data = credential.authorizationCode {
        authCode = String(data: data, encoding: .utf8) ?? ""
    }
	
    // 필요한 로직들 추가
}

그런데, 2번째 로그인부터는 email을 내려주지 않는다. ( email == "" )

 

애플로그인 -> 앱 회원가입 -> 회원가입 끝

  

위와 같은 회원가입 과정에서, 애플로그인만 하고 앱을 종료한 뒤, 다시 가입하려고 할 때

앱 회원가입에 email이 필요한 경우라면 문제가 발생한다. ( email을 못받아오니까 )

 

하지만 로그인할 때 마다 email을 얻을 수 있다 (?)

credential.identityToken을 이용하면 된다.

 

해당 토큰은 JWT 토큰으로, https://jwt.io/ 에서 빠른 확인 가능하다.

아니 이럴꺼면 email 값은 왜 비운거야 걍 내려주지

 

credential.identityToken을 디코딩 해야하는데,

각종 라이브러리를 이용하는 방법이 있지만, Swift 코드만으로도 가능하다.

( 개인적으로 라이브러리를 추가하는 걸 싫어한다. 빌드시간 넘모 길어요 ㅠ,ㅜ )

 

코드는 아래와 같다.

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
    
    guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else {
        return
    }

    var email = credential.email ?? ""
    let user = credential.user
    var authCode = ""
    if let data = credential.authorizationCode {
        authCode = String(data: data, encoding: .utf8) ?? ""
    }

    if email.isEmpty { /// 2번째 애플 로그인부터는 email이 identityToken에 들어있음.
        if let tokenString = String(data: credential.identityToken ?? Data(), encoding: .utf8) {
            email = decode(jwtToken: tokenString)["email"] as? String ?? ""
        }
    }
    
    // 필요한 로직들
}


/// JWTToken -> dictionary
private func decode(jwtToken jwt: String) -> [String: Any] {
    
    func base64UrlDecode(_ value: String) -> Data? {
        var base64 = value
            .replacingOccurrences(of: "-", with: "+")
            .replacingOccurrences(of: "_", with: "/")

        let length = Double(base64.lengthOfBytes(using: String.Encoding.utf8))
        let requiredLength = 4 * ceil(length / 4.0)
        let paddingLength = requiredLength - length
        if paddingLength > 0 {
            let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0)
            base64 = base64 + padding
        }
        return Data(base64Encoded: base64, options: .ignoreUnknownCharacters)
    }

    func decodeJWTPart(_ value: String) -> [String: Any]? {
        guard let bodyData = base64UrlDecode(value),
              let json = try? JSONSerialization.jsonObject(with: bodyData, options: []), let payload = json as? [String: Any] else {
            return nil
        }

        return payload
    }
    
    let segments = jwt.components(separatedBy: ".")
    return decodeJWTPart(segments[1]) ?? [:]
}

 

 

Comments