중요합니다
2025년 5월 1일부터 새 고객을 위해 Azure AD B2C를 더 이상 구매할 수 없습니다. FAQ에서 자세히 알아보세요.
이 문서에서는 사용자 고유의 iOS Swift 모바일 애플리케이션에 Azure AD B2C(Azure Active Directory B2C) 인증을 추가하는 방법을 보여 줍니다. iOS용 MSAL(Microsoft 인증 라이브러리)과 iOS Swift 애플리케이션을 통합하는 방법을 알아봅니다.
샘플 iOS Swift 애플리케이션에서 인증 구성과 함께 이 문서를 사용하여 사용자 고유의 iOS Swift 앱으로 샘플 iOS Swift 앱을 대체합니다. 이 문서의 지침을 완료하면 애플리케이션에서 Azure AD B2C를 통해 로그인을 수락합니다.
필수 조건
Azure AD B2C를 사용하여 샘플 iOS Swift 앱에서 인증 구성의 필수 구성 요소 및 통합 지침을 검토합니다.
iOS Swift 앱 프로젝트 만들기
iOS Swift 애플리케이션이 아직 없는 경우 다음 단계를 수행하여 새 프로젝트를 설정합니다.
- Xcode를 열고새>파일>프로젝트를 선택합니다.
- iOS 앱의 경우 iOS>앱을 선택한 다음, 다음을 선택합니다.
-
새 프로젝트에 대한 선택 옵션의 경우 다음을 제공합니다.
-
제품 이름(예:
MSALiOS
. -
조직 식별자(예:
contoso.com
. - 인터페이스의 경우 Storyboard를 선택합니다.
- 수명 주기에 대해 UIKit 앱 대리자를 선택합니다.
- 언어에 대해 Swift를 선택합니다.
-
제품 이름(예:
- 다음을 선택합니다.
- 앱을 만들 폴더를 선택한 다음 만들기를 선택합니다.
1단계: MSAL 라이브러리 설치
CocoaPods를 사용하여 MSAL 라이브러리를 설치합니다. 프로젝트의 .xcodeproj 파일과 동일한 폴더에서 podfile 파일이 없으면 빈 파일을 만들고 이름을 podfile로 지정합니다. podfile 파일에 다음 코드를 추가합니다.
use_frameworks! target '<your-target-here>' do pod 'MSAL' end
프로젝트 이름(예:
<your-target-here>
)으로MSALiOS
를 바꾸십시오. 자세한 내용은 Podfile 구문 참조를 참조하세요.터미널 창에서 podfile 파일이 포함된 폴더로 이동한 다음 Pod 설치 를 실행하여 MSAL 라이브러리를 설치합니다.
명령을
pod install
파일이 만들어집니다<. Xcode에서 프로젝트를 다시 로드하려면 Xcode를 닫은 다음 프로젝트 name.xcworkspace< 파일을 엽니다>.
2단계: 앱 URL 구성표 설정
사용자가 인증하면 Azure AD B2C는 Azure AD B2C 애플리케이션 등록에 구성된 리디렉션 URI를 사용하여 권한 부여 코드를 앱에 보냅니다.
MSAL 기본 리디렉션 URI 형식은 msauth.[Your_Bundle_Id]://auth
. 예를 들어 msauth.com.microsoft.identitysample.MSALiOS://auth
URL 구성표는 다음과 msauth.com.microsoft.identitysample.MSALiOS
같습니다.
이 단계에서는 배열을 사용하여 URL 체계를 등록합니다 CFBundleURLSchemes
. 애플리케이션은 Azure AD B2C의 콜백에 대한 URL 체계를 수신 대기합니다.
Xcode에서 Info.plist 파일을 소스 코드 파일로 엽니다.
<dict>
섹션에서 다음 XML 코드 조각을 추가합니다.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.com.microsoft.identitysample.MSALiOS</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msauthv2</string>
<string>msauthv3</string>
</array>
3단계: 인증 코드 추가
샘플 코드는 클래스로 UIViewController
구성됩니다. 수업:
- 사용자 인터페이스의 구조를 정의합니다.
- Azure AD B2C ID 공급자에 대한 정보를 포함합니다. 앱은 이 정보를 사용하여 Azure AD B2C와 트러스트 관계를 설정합니다.
- 사용자를 인증하고, 토큰을 획득하고, 유효성을 검사하는 인증 코드를 포함합니다.
사용자가 인증하는 UIViewController
위치를 선택합니다.
UIViewController
의 코드를 GitHub에 제공된 코드와 병합하세요.
4단계: iOS Swift 앱 구성
인증 코드를 추가한 후 Azure AD B2C 설정을 사용하여 iOS Swift 앱을 구성합니다. Azure AD B2C ID 공급자 설정은 이전 섹션에서 선택한 클래스에서 구성 UIViewController
됩니다.
iOS Swift 앱을 구성하는 방법을 알아보려면 Azure AD B2C를 사용하여 샘플 iOS Swift 앱에서 인증 구성을 참조하세요.
5단계: 모바일 앱 실행 및 테스트
- 연결된 iOS 디바이스의 시뮬레이터를 사용하여 프로젝트를 빌드하고 실행합니다.
- 로그인을 선택한 다음, Azure AD B2C 로컬 또는 소셜 계정으로 등록하거나 로그인합니다.
- 성공적으로 인증되면 탐색 모음에 표시 이름이 표시됩니다.
6단계: 코드 구성 요소 사용자 지정
이 섹션에서는 iOS Swift 앱에 인증을 사용하도록 설정하는 코드 구성 요소에 대해 설명합니다. UIViewController의 메서드를 나열하고 코드를 사용자 지정하는 방법을 설명합니다.
6.1단계: 공용 클라이언트 애플리케이션 인스턴스화
퍼블릭 클라이언트 애플리케이션은 애플리케이션 비밀을 안전하게 유지하기 위해 신뢰할 수 없으며 클라이언트 비밀이 없습니다. viewDidLoad에서 공용 클라이언트 애플리케이션 개체를 사용하여 MSAL을 인스턴스화합니다.
다음 Swift 코드 조각은 구성 개체를 사용하여 MSAL MSALPublicClientApplicationConfig
을 초기화하는 방법을 보여 줍니다.
구성 개체는 Azure AD B2C 환경에 대한 정보를 제공합니다. 예를 들어 Azure AD B2C에 대한 인증 요청을 빌드하는 클라이언트 ID, 리디렉션 URI 및 권한을 제공합니다. 구성 개체에 대한 자세한 내용은 샘플 모바일 앱 구성을 참조하세요.
do {
let signinPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: kRedirectUri, authority: signinPolicyAuthority)
pcaConfig.knownAuthorities = [signinPolicyAuthority, editProfileAuthority]
self.applicationContext = try MSALPublicClientApplication(configuration: pcaConfig)
self.initWebViewParams()
} catch {
self.updateLoggingText(text: "Unable to create application \(error)")
}
이 메서드는 initWebViewParams
대화형 인증 환경을 구성합니다.
다음 Swift 코드 조각은 시스템 웹 보기를 사용하여 webViewParameters
클래스 멤버를 초기화합니다. 자세한 내용은 iOS/macOS용 브라우저 및 WebViews 사용자 지정을 참조하세요.
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
self.webViewParameters?.webviewType = .default
}
6.2단계: 대화형 권한 부여 요청 시작
대화형 권한 부여 요청은 사용자에게 시스템 웹 보기를 사용하여 등록 또는 로그인하라는 메시지가 표시되는 흐름입니다. 사용자가 로그인 단추를 선택하면 메서드가 authorizationButton
호출됩니다.
authorizationButton
메서드는 권한 부여 요청에 대한 관련 데이터를 사용하여 MSALInteractiveTokenParameters
객체를 준비합니다.
acquireToken
메서드는 MSALInteractiveTokenParameters
를 사용하여 시스템 웹 보기를 통해 사용자를 인증합니다.
다음 코드 조각은 대화형 권한 부여 요청을 시작하는 방법을 보여 줍니다.
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: self.webViewParameters!)
parameters.promptType = .selectAccount
parameters.authority = authority
applicationContext.acquireToken(with: parameters) { (result, error) in
// On error code
guard let result = result else {
self.updateLoggingText(text: "Could not acquire token: \(error ?? "No error information" as! Error)")
return
}
// On success code
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "Empty")")
}
사용자가 권한 부여 흐름을 성공적으로 완료하든 실패하든 그 결과는 메서드의 acquireToken
로 반환됩니다.
메서드는 acquireToken
및 result
개체를 반환합니다. 이 클로저를 사용하여 다음을 수행합니다.
- 인증이 완료된 후 정보로 모바일 앱 UI를 업데이트합니다.
- 액세스 토큰을 사용하여 웹 API 서비스를 호출합니다.
- 인증 오류(예: 사용자가 로그인 흐름을 취소하는 경우)를 처리합니다.
6.3단계: 웹 API 호출
토큰 기반 권한 부여 웹 API를 호출하려면 앱에 유효한 액세스 토큰이 필요합니다. 앱은 다음을 수행합니다.
- 웹 API 엔드포인트에 필요한 권한(범위)을 사용하여 액세스 토큰을 획득합니다.
- 다음 형식을 사용하여 HTTP 요청의 권한 부여 헤더에서 액세스 토큰을 전달자 토큰으로 전달합니다.
Authorization: Bearer <access-token>
사용자가 대화형으로 인증하면 앱은 닫기에서 액세스 토큰을 acquireToken
가져옵니다. 후속 웹 API 호출의 경우 이 섹션에서 설명된 조용히(acquireTokenSilent
) 획득 토큰 메서드를 사용합니다.
메서드는 acquireTokenSilent
다음 작업을 수행합니다.
- 토큰 캐시에서 요청된 범위가 있는 액세스 토큰을 가져오려고 시도합니다. 토큰이 있고 만료되지 않은 경우 토큰이 반환됩니다.
- 토큰이 토큰 캐시에 없거나 토큰이 만료된 경우 MSAL 라이브러리는 새로 고침 토큰을 사용하여 새 액세스 토큰을 획득하려고 시도합니다.
- 새로 고침 토큰이 없거나 만료된 경우 예외가 반환됩니다. 이 경우 대화 형으로 로그인하라는 메시지를 사용자에게 표시해야 합니다.
다음 코드 조각은 액세스 토큰을 획득하는 방법을 보여 줍니다.
do {
// Get the authority using the sign-in or sign-up user flow
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
// Get the current account from the application context
guard let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy) else {
self.updateLoggingText(text: "There is no account available!")
return
}
// Configure the acquire token silent parameters
let parameters = MSALSilentTokenParameters(scopes: kScopes, account:thisAccount)
parameters.authority = authority
parameters.loginHint = "username"
// Acquire token silent
self.applicationContext.acquireTokenSilent(with: parameters) { (result, error) in
if let error = error {
let nsError = error as NSError
// interactionRequired means we need to ask the user to sign in. This usually happens
// when the user's Refresh Token is expired or if the user has changed their password
// among other possible reasons.
if (nsError.___domain == MSALErrorDomain) {
if (nsError.code == MSALError.interactionRequired.rawValue) {
// Start an interactive authorization code
// Notice we supply the account here. This ensures we acquire token for the same account
// as we originally authenticated.
...
}
}
self.updateLoggingText(text: "Could not acquire token: \(error)")
return
}
guard let result = result else {
self.updateLoggingText(text: "Could not acquire token: No result returned")
return
}
// On success, set the access token to the accessToken class member.
// The callGraphAPI method uses the access token to call a web API
self.accessToken = result.accessToken
...
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}
이 메서드는 callGraphAPI
액세스 토큰을 검색하고 다음과 같이 웹 API를 호출합니다.
@objc func callGraphAPI(_ sender: UIButton) {
guard let accessToken = self.accessToken else {
self.updateLoggingText(text: "Operation failed because could not find an access token!")
return
}
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30
let url = URL(string: self.kGraphURI)
var request = URLRequest(url: url!)
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
self.updateLoggingText(text: "Calling the API....")
urlSession.dataTask(with: request) { data, response, error in
guard let validData = data else {
self.updateLoggingText(text: "Could not call API: \(error ?? "No error information" as! Error)")
return
}
let result = try? JSONSerialization.jsonObject(with: validData, options: [])
guard let validResult = result as? [String: Any] else {
self.updateLoggingText(text: "Nothing returned from API")
return
}
self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
}.resume()
}
6.4단계: 사용자 로그아웃
MSAL을 사용하여 로그아웃하면 애플리케이션에서 사용자에 대한 알려진 모든 정보가 제거됩니다. 로그아웃 방법을 사용하여 사용자를 로그아웃하고 UI를 업데이트합니다. 예를 들어 보호된 UI 요소를 숨기거나, 로그아웃 단추를 숨기거나, 로그인 단추를 표시할 수 있습니다.
다음 코드 조각은 사용자를 로그아웃하는 방법을 보여 줍니다.
@objc func signoutButton(_ sender: UIButton) {
do {
let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy)
if let accountToRemove = thisAccount {
try applicationContext.remove(accountToRemove)
} else {
self.updateLoggingText(text: "There is no account to signing out!")
}
...
} catch {
self.updateLoggingText(text: "Received error signing out: \(error)")
}
}
다음 단계
알아보기: