---
source_url: "https://workos.com/blog/apple-app-store-authentication-sign-in-with-apple-2025"
title: How to add auth to your Apple app in order to be listed in the Apple Store in 2025 — WorkOS
mirrored_at: 2026-08-19T01:00:58.602Z
host: workos.com
cited_in_42a: true
mirror_canonical: "https://index.42a.ai/workos.com/blog/apple-app-store-authentication-sign-in-with-apple-2025"
---

> **Original source:** https://workos.com/blog/apple-app-store-authentication-sign-in-with-apple-2025

When preparing to launch your iOS app in the Apple App Store in 2025, one of the first hurdles is meeting Apple’s authentication requirements. Apple is strict about how users sign in, especially if your app supports third-party logins like Google, Facebook, GitHub, or Twitter. To pass App Review, you’ll often need to implement Sign in with Apple alongside your other login methods.

In this article, we’ll walk through Apple’s latest rules and show you how to add compliant authentication to your iOS app using [WorkOS AuthKit](https://www.authkit.com/), combining Sign in with Apple with other social login providers.

## **The core rule: Social logins require an alternative**

Apple’s App Store guidelines make it clear:

-   If you offer any third-party login (like Google Sign-In), you must also provide an equivalent, privacy-focused login option.
-   The most common and Apple-approved way to do this is by offering **Sign in with Apple**.

Why? Because Sign in with Apple guarantees privacy features that other login providers typically don’t:

-   It collects only the minimum user data (name + email).
-   It allows users to hide their email address using Apple’s relay service.
-   It does not track users across different apps or websites.

Without this, your app is at high risk of being rejected during review.

## **When Sign in with Apple is required**

Here’s when you must add it:

-   You provide login via Google, Facebook, Twitter, GitHub, or any other social service.
-   You offer login via multiple identity providers, but none of them meet Apple’s privacy standard.

In short: if you let people sign in with Google, you should also support Sign in with Apple.

## **When Sign in with Apple is not required**

There are some exceptions. You don’t need Sign in with Apple if:

-   You only offer your own proprietary login system (e.g., email + password).
-   Your app is designed specifically for enterprise or education accounts (e.g., Microsoft Azure AD, Google Workspace SSO).
-   Your app uses a government or industry-backed ID system (like a national eID).
-   Your app is a client for a specific service (e.g., a Dropbox client that only signs into Dropbox).

If you fall into one of these categories, you may skip Sign in with Apple, but be prepared to explain this to App Review if questioned.

## **How to add auth to your Apple app using WorkOS**

You can meet Apple’s requirement and support Sign in with Apple plus other social logins using [WorkOS AuthKit](https://www.authkit.com/) with a hosted login and [OAuth 2.0 PKCE](https://workos.com/blog/secure-authentication-for-frontend-apps-with-pkce) from your native app. Below is an end-to-end outline you can adapt.

### **What we’ll build**

1.  Start the login from your iOS app.
2.  Present the WorkOS hosted login (which shows Sign in with Apple and any other providers you enable) in a secure system browser context.
3.  Handle the OAuth redirect URI to capture the authorization code.
4.  Exchange the code for tokens using PKCE (no client secret in the app).
5.  Retrieve the user profile and persist a session.

### **Prerequisites**

-   A [WorkOS account](https://dashboard.workos.com/)
-   Your WorkOS [API Key](https://workos.com/docs/glossary/api-key) and [Client ID](https://workos.com/docs/glossary/client-id)

![](https://cdn.prod.website-files.com/621f84dc15b5ed16dc85a18a/677462897cfcc1e25043c6e7_01.webp)

-   Activate AuthKit in your [WorkOS Dashboard](https://dashboard.workos.com/get-started) if you haven’t already. In the _Overview_ section, click the _Set up User Management_ button and follow the instructions. If you don’t see the option, AuthKit is activated already.
-   An OAuth Redirect URI you control (e.g., a custom URL scheme `myapp://auth/callback` or a Universal Link)
-   iOS target using `ASWebAuthenticationSession` (iOS 12+)

### **1\. Configure a redirect URI**

A redirect URI is the callback endpoint that WorkOS will redirect to **after** a user has authenticated.

You can set a redirect URI in [the _Redirects_ section of the WorkOS Dashboard](https://dashboard.workos.com/environment/redirects).

![](https://cdn.prod.website-files.com/621f84dc15b5ed16dc85a18a/68a5db5ebcfae36498ed4027_9.webp)

When users sign out of their application, they will be redirected to your app’s [Logout redirect](https://workos.com/docs/authkit/sessions/configuring-sessions/logout-redirect) location which is configured in the same dashboard area.

### **2\. Configure the login endpoint**

Login requests should originate from your application. In some instances, requests may not begin at your app. For example, some users might bookmark the hosted login page or they might be led directly to the hosted login page when clicking on a password reset link in an email.

In these cases, AuthKit will detect when a login request did not originate at your application and redirect to your application’s login endpoint. This is an endpoint that you define at your application that redirects users to sign in using AuthKit. We’ll create this endpoint in the next step.

You can configure the login endpoint in [the _Redirects_ section of the WorkOS Dashboard](https://dashboard.workos.com/environment/redirects).

### **3\. Set secrets in your app**

To make calls to WorkOS, provide the API key and the client ID. Store these values as managed secrets and pass them to the SDKs either as environment variables or directly in your app’s configuration depending on your preferences.

	
`WORKOS_API_KEY='sk_test_123' WORKOS_CLIENT_ID='project_123'`
	

### **4\. Configure Sign in with Apple**

For step-by-step instructions, see [How to set up “Sign in with Apple”](https://workos.com/docs/integrations/apple).

The configuration process involves the following steps:

1.  Enable Sign in with Apple at the WorkOS Dashboard and get the _Redirect URI_ and _Outbound email domains_ values.
2.  Get the _Apple Team ID_, _Apple Service ID_, _Apple Private Key_, and _Private Key ID_ from your Apple Developer account.
3.  Configure the Apple credentials you retrieved in the WorkOS Dashboard.
4.  Set up Private Email Relay.

### **5\. (Optional) Configure other authentication options**

You can configure more OAuth providers like Google, GitHub, LinkedIn, etc. For instructions see the [Social Login](https://workos.com/docs/authkit/social-login) docs.

You can also add [passwordless authentication](https://workos.com/docs/authkit/magic-auth), [email/password authentication](https://workos.com/docs/authkit/email-password), or [passkeys](https://workos.com/docs/authkit/passkeys).

### **6\. Build the OAuth Authorization URL & start the authentication flow**

Your app will open the [WorkOS authorize endpoint](https://workos.com/docs/reference/authkit/authentication/get-authorization-url) with:

-   `response_type=code`
-   `client_id=YOUR_WORKOS_CLIENT_ID`
-   `redirect_uri=YOUR_REDIRECT_URI`
-   `code_challenge` and `code_challenge_method=S256` (PKCE)
    -   Compute the `code_challenge` locally. See the next step for an example.
-   `provider=authkit`  
    -   AuthKit will take care of detecting the user’s authentication method, such as identifying whether they use Email + Password or Single Sign-On,and direct them to the corresponding login flow.
-   Optional `state` for CSRF protection

Use Apple’s secure system browser flow (preferred by App Review) instead of a raw WebView.

  `import AuthenticationServices import CommonCrypto  final class AuthCoordinator: NSObject {   private var session: ASWebAuthenticationSession?   private var codeVerifier = ""    func startLogin() {     // 1) Create PKCE     codeVerifier = randomURLSafeString(64)     let codeChallenge = base64URLEncode(sha256(codeVerifier))      // 2) Build authorization URL     let clientId = "YOUR_WORKOS_CLIENT_ID"     let redirectUri = "myapp://auth/callback" // or a Universal Link      var comps = URLComponents(string: "https://api.workos.com/user_management/authorize")!     comps.queryItems = [       .init(name: "response_type", value: "code"),       .init(name: "client_id", value: clientId),       .init(name: "redirect_uri", value: redirectUri),       .init(name: "code_challenge", value: codeChallenge),       .init(name: "code_challenge_method", value: "S256"),       .init(name: "provider", value: "authkit"), // AuthKit will detect the auth methods you enabled       .init(name: "state", value: UUID().uuidString),     ]      let authURL = comps.url!      // 3) Start secure browser session     session = ASWebAuthenticationSession(       url: authURL,       callbackURLScheme: "myapp"     ) { [weak self] callbackURL, error in       guard let self,             let callbackURL,             error == nil       else { return }        let items = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false)?.queryItems       if let code = items?.first(where: { $0.name == "code" })?.value {         self.exchangeCodeForTokens(           code: code,           codeVerifier: self.codeVerifier,           redirectUri: redirectUri         )       }     }      session?.presentationContextProvider = self     session?.prefersEphemeralWebBrowserSession = true // nice-to-have for privacy     session?.start()   }    private func exchangeCodeForTokens(code: String, codeVerifier: String, redirectUri: String) {     // See next step for token exchange details   } }  extension AuthCoordinator: ASWebAuthenticationPresentationContextProviding {   func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {     UIApplication.shared.connectedScenes       .compactMap { ($0 as? UIWindowScene)?.keyWindow }       .first ?? ASPresentationAnchor()   } }  // ---- PKCE helpers (sketch) ---- func randomURLSafeString(_ length: Int) -> String {   /* generate base64url-safe random string */ }  func sha256(_ input: String) -> Data {   /* digest */ }  func base64URLEncode(_ data: Data) -> String {   /* base64url encode without padding */ }`
  

### **8\. Exchange the code for a token**

Call the WorkOS token endpoint with:

-   `grant_type=authorization_code`
-   `code`
-   `redirect_uri`
-   `client_id`
-   `code_verifier`

Pseudo-request (Swift URLSession):

  `struct TokenResponse: Decodable {   let access_token: String   let id_token: String?   let token_type: String   let expires_in: Int   let refresh_token: String? }  func exchangeCodeForTokens(   code: String,   codeVerifier: String,   redirectUri: String,   completion: @escaping (Result<TokenResponse, Error>) -> Void ) {   var req = URLRequest(     url: URL(string: "https://api.workos.com/user_management/authenticate")!   )   req.httpMethod = "POST"   req.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")    let params: [String: String] = [     "grant_type": "authorization_code",     "code": code,     "redirect_uri": redirectUri,     "client_id": "WORKOS_OAUTH_CLIENT_ID",     "code_verifier": codeVerifier,   ]    req.httpBody = params     .map {       "\($0.key)=\($0.value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)"     }     .joined(separator: "&")     .data(using: .utf8)    URLSession.shared.dataTask(with: req) { data, _, error in     if let error = error {       return completion(.failure(error))     }     guard let data = data else {       return completion(.failure(NSError(domain: "no_data", code: 0)))     }     do {       let tokens = try JSONDecoder().decode(TokenResponse.self, from: data)       completion(.success(tokens))     } catch {       completion(.failure(error))     }   }.resume() }`

  

Your user is now logged in.

The decoded response looks like this:

	
`{   "user": {     "object": "user",     "id": "user_01E4ZCR3C56J083X43JQXF3JK5",     "email": "marcelina.davis@example.com",     "first_name": "Marcelina",     "last_name": "Davis",     "email_verified": true,     "profile_picture_url": "https://workoscdn.com/images/v1/123abc",     "created_at": "2021-06-25T19:07:33.155Z",     "updated_at": "2021-06-25T19:07:33.155Z"   },   "organization_id": "org_01H945H0YD4F97JN9MATX7BYAG",   "access_token": "eyJhb.nNzb19vaWRjX2tleV9.lc5Uk4yWVk5In0",   "refresh_token": "yAjhKk123NLIjdrBdGZPf8pLIDvK" }`
	

### **9\. Ending the session**

Logging out is just as important as logging in. Apple reviewers often check for it, and users expect a clear way to end their session. From a security perspective, logout ensures access tokens don’t linger on the device.

A complete logout flow has three parts:

1.  Call the [WorkOS logout endpoint](https://workos.com/docs/reference/authkit/logout), which will invalidate the user’s session server-side. This ensures that if they return later, they’ll have to authenticate again.
2.  After successfully signing out, the user will be redirected to your app’s [Logout redirect](https://workos.com/docs/authkit/sessions/configuring-sessions/logout-redirect) location, which is configured in the WorkOS dashboard.
3.  Remove access and refresh tokens from secure storage (e.g., the Keychain).

### **Security best practices**

-   Always use PKCE in mobile clients.
-   Never ship client secrets in the app.
-   [Validate ID Tokens](https://workos.com/guide/jwt-validation) (iss/aud/exp/nbf/signature).
-   Use Keychain for token storage.
-   Rotate keys and monitor login telemetry.

## **Wrapping up**

Apple’s rules on authentication can feel like a moving target, but the core principle is clear: if you let users sign in with Google, Facebook, or any other third-party provider, you also need to offer a privacy-focused alternative. In practice, that means supporting Sign in with Apple.

With WorkOS AuthKit, you can handle Sign in with Apple alongside your other providers through a single OAuth PKCE flow. This keeps your app compliant, your code secure, and your users happy.