소셜 로그인 구현하기

2025. 1. 3. 15:48·iOS/Framework
반응형

👋 들어가기 전

 

드디어 우리 서비스에 Authorization 기능이 도입된다.

iOS 개발이면 처음은 무조건 apple login이다.

현재는 swiftUI 기반이지만, uikit에서 다른 절차가 필요하면 추후 따로 구분하자.


🍎 애플 로그인

1.  Signing & Capabilities 

 

다음과 같이 Capability에 Sign in with Apple을 추가한다.

 

2.  Auth Manager 객체 설계

먼저 AuthManager에 필요한 다양한 변수화 함수를 프로토콜로 정의한다.
구글도 함께 테스트할테니 구글 관련된 것도 한꺼번에 정의

protocol Authable {
    func buildAppleAuth() // appleAuth를 위한 build
    func buildGoogleAuth() // googleAuth를 위한 build
    func buildAuth() // 모든 소셜 auth build
    func loginWithApple() // 애플 로그인
    func loginWithGoogle() // 구글 로그인
}

3 .  apple auth 빌드 

인증과 관련된 스코프, 델리게이트, context 제공자를 명시한다.

func buildAppleAuth() {
    let appleIdProvider = ASAuthorizationAppleIDProvider()
    let request: ASAuthorizationAppleIDRequest = appleIdProvider.createRequest()
    request.requestedScopes = [.fullName, .email] // auth로 부터 받아올 scope 정의
    let auth = ASAuthorizationController(authorizationRequests: [request]) // auth 객체 생성
    auth.delegate = self // 델리게이터 지정
    auth.presentationContextProvider = self // 애플 로그인 창을 띄울 컨텍스트 제공
    self._appleAuth =  auth
}

4. delegate  및  PresentationContextProviding 정의

인증 성공과 실패에 대한 동작을 정의하고, 로그인 화면을 앱 최상단에 보여준다.

extension AuthManager: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first ?? .init() // 로그인 창 위치 지정 (최상단)
    }

    // 성공
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
           let rawData = credential.identityToken {
           let token = String(decoding: rawData, as: UTF8.self)
            print("Email: \(credential), name: \(credential.fullName), token: \(token)")
        }
    }

    // 실패
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) {
        print(error.localizedDescription)
    }
}

5.  로그인 실행 함수 정의 및 뷰에서 호출

뷰에서 로그인을 호출할 수 있는 함수를 명시해 로그인 기능을 실행한다.

// AuthManager.swift
func loginWithApple() {
    _appleAuth?.performRequests()
}

// ContentView.swift


struct ContentView: View {

    private var authManager = AuthManager()

    var body: some View {
        VStack {
            Button {
                authManager.loginWithApple()
            } label: {
                Text("Login")
                    .foregroundStyle(.white)
            }
            .frame(maxWidth: .infinity, maxHeight: 56)
            .background(
                RoundedRectangle(cornerRadius: 20)
                    .foregroundStyle(.blue)
            )

        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .padding(.horizontal, 20)
    }
}

 

6. 결과 화면

보안을 위해 화면을 좀 짤라지만 토큰과 정보들이 잘 내려오는 것을 확인할 수 있다.

 


🛜 구글 로그인

1. 패키지 다운로드

애플과 달리 구글은 ThirdParty 이므로 패키지 설치부터 진행한다.

https://github.com/google/GoogleSignIn-iOS

 

2. client ID 발급 받기

https://developers.google.com/identity/sign-in/ios/start-integrating

 

iOS 및 macOS용 Google 로그인 시작하기  |  Authentication  |  Google for Developers

중요: 2024년 5월 1일부터 Apple에서는 GoogleSignIn-iOS와 같이 흔히 사용되는 SDK를 사용하는 iOS 애플리케이션의 개인 정보 보호 매니페스트 및 서명을 요구합니다. 2024년 5월 1일 전에 GoogleSignIn-iOS v7.1.0

developers.google.com

 

구글 개발자 사이트에 들어가서 client ID를 발급 받거나 기존에 있다면 가져오자.

다음과 같이 Bundle ID는 앱의 Bundle ID를 넣어준다.

 

위 과정이 끝나면 다음과 같이 Client ID를 발급받는데 꼭 복사해 놓자.
만약 깜빡했다면 create 밑에 있는 하얀색 버튼을 누르면 Google Cloud Platform에 접속되는데
거기서 확인할 수 있다.

 

3. GIDClientID  및 URL 스키마 추가하기

다음과 같이 info.plist에 GIDClientID를 설정한다.

Key: GIDClientID,  value는 String 타입으로 발급 받은 키를 넣어준다.

 

이전 내 기억으로는 clientID를 코드로 넣었던 기억이 있는데 지금은
plist에 등록하면 알아서 읽어오는 듯

 

 

이후 발급 받은 clientID값을 역순으로 URL Types의 URL Schemes에 넣어준다.

// Client ID: 1234567890-abcdefg.apps.googleusercontent.com 라면
com.googleusercontent.apps.1234567890-abcdefg // 이렇게 적용시키면 된다.

 

4. Appdelegate 정의 (UIKit) / openURL 설정 (SwiftUI)

UIKit에서는 Appdelegate에 다음과 같이 정의 해야한다.

// Appdelegate.swift
import Foundation
import UIKit
import GoogleSignIn

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        return true
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return GIDSignIn.sharedInstance.handle(url) // 구글 로그인 요청이 들어왔을 때 해당 함수를 통하여 로그인 화면이 로드된다.
    }
}

 

swiftUI에는 보다 간편하게 설정할 수 있다.

@main
struct MyApp: App {

  var body: some Scene {
    WindowGroup {
      ContentView()
        // ...
        .onOpenURL { url in
          GIDSignIn.sharedInstance.handle(url)
        }
    }
  }
}

5.  로그인 함수 정의

// AuthManager.swift

func loginWithGoogle() {
    GIDSignIn.sharedInstance.signIn(withPresenting: _window.rootViewController ?? UIViewController()) { result, error in
        print("Result: \(result)")
        print("Error: \(error)")
    }
}

👍전체 코드

// AuthManager.swift

import SwiftUI
import AuthenticationServices
import GoogleSignIn

protocol Authable {
    func buildAppleAuth() // appleAuth를 위한 build
    func buildAuth() // 모든 소셜 auth build
    func loginWithApple() // 애플 로그인
    func loginWithGoogle() // 구글 로그인
}

final class AuthManager: NSObject, Authable {
    private var _appleAuth: ASAuthorizationController?
    private var _googleConfiguration: GIDConfiguration?
    private let _window: UIWindow = (UIApplication.shared.connectedScenes.first as? UIWindowScene)?.windows.first ?? .init()

    override init() {
        super.init()
        buildAuth()
    }

    func buildAppleAuth() {
        let appleIdProvider = ASAuthorizationAppleIDProvider()
        let request: ASAuthorizationAppleIDRequest = appleIdProvider.createRequest()
        request.requestedScopes = [.fullName, .email] // auth로 부터 받아올 scope 정의
        let auth = ASAuthorizationController(authorizationRequests: [request]) // auth 객체 생성
        auth.delegate = self // 델리게이터 지정
        auth.presentationContextProvider = self // 애플 로그인 창을 띄울 컨텍스트 제공
        self._appleAuth =  auth
    }

    func buildAuth() {
        buildAppleAuth()
    }

    func loginWithApple() {
        _appleAuth?.performRequests()
    }

    func loginWithGoogle() {
        GIDSignIn.sharedInstance.signIn(withPresenting: _window.rootViewController ?? UIViewController()) { result, error in
            print("Result: \(result)")
            print("Error: \(error)")
        }
    }

}

extension AuthManager: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return _window // 로그인 창 위치 지정 (최상단)
    }

    // 성공
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
           let rawData = credential.identityToken {
           let token = String(decoding: rawData, as: UTF8.self)
            print("Email: \(credential), name: \(credential.fullName), token: \(token)")
        }
    }

    // 실패
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) {
        print(error.localizedDescription)
    }
}

😀 소감 및 마무리

서비스가 커질수록 다양한 소셜 로그인을 사용할 것 같다.
앞으로 다양한 소셜 로그인도 계속 이 포스팅에 정리하여 추후 로그인 기능을 구현할 때
시간을 많이 절약해보자.


출처

 

Sign in with Apple | Apple Developer Documentation

Sign in with Apple provides a fast, private way to sign into apps and websites, giving people a consistent experience they can trust and the convenience of not having to remember multiple accounts and passwords.

developer.apple.com

 

 

iOS 또는 macOS 앱에 Google 로그인 통합  |  Authentication  |  Google for Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 iOS 또는 macOS 앱에 Google 로그인 통합 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 페

developers.google.com

 

반응형

'iOS > Framework' 카테고리의 다른 글

AVAssetTrack  (0) 2025.04.06
AVFoundation (4) [AVAudioSession]  (3) 2024.10.22
AVFoundation (3) [AVPlayerLayer]  (1) 2024.10.22
AVFoundation (2) [AVPlayer, AVPlayerItem]  (0) 2024.10.21
AVKit  (4) 2024.10.21
'iOS/Framework' 카테고리의 다른 글
  • AVAssetTrack
  • AVFoundation (4) [AVAudioSession]
  • AVFoundation (3) [AVPlayerLayer]
  • AVFoundation (2) [AVPlayer, AVPlayerItem]
Hamp
Hamp
남들에게 보여주기 부끄러운 잡다한 글을 적어 나가는 자칭 기술 블로그입니다.
  • Hamp
    Hamp의 분리수거함
    Hamp
  • 전체
    오늘
    어제
    • 분류 전체보기 (308) N
      • CS (30)
        • 객체지향 (2)
        • Network (7)
        • OS (6)
        • 자료구조 (1)
        • LiveStreaming (3)
        • 이미지 (1)
        • 잡다한 질문 정리 (0)
        • Hardware (2)
        • 이론 (6)
        • 컴퓨터 그래픽스 (0)
      • Firebase (3)
      • Programing Langauge (38) N
        • swift (32)
        • python (5) N
        • Kotlin (1)
      • iOS (132)
        • UIKit (37)
        • Combine (1)
        • SwiftUI (32)
        • Framework (7)
        • Swift Concurrency (22)
        • Tuist (6)
        • Setting (11)
        • Modularization (1)
        • Instruments (6)
      • PS (59)
        • 프로그래머스 (24)
        • 백준 (13)
        • LeetCode (19)
        • 알고리즘 (3)
      • Git (18)
        • 명령어 (4)
        • 이론 (2)
        • hooks (1)
        • config (2)
        • action (7)
      • Shell Script (2)
      • Linux (6)
        • 명령어 (5)
      • Spring (15) N
        • 어노테이션 (3) N
        • 튜토리얼 (11)
      • CI-CD (4)
      • Android (0)
        • Jetpack Compose (0)
      • AI (1) N
        • 이론 (1) N
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    IOS
    dfs
    dispatch
    boostcamp
    lifecycle
    concurrency
    Swift
    property
    Tuist
    dp
    투포인터
    CS
    백준
    SwiftUI
    GIT
    AVFoundation
    프로그래머스
    protocol
    Spring
    UIKit
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.0
Hamp
소셜 로그인 구현하기
상단으로

티스토리툴바