In this article
August 19, 2025
August 19, 2025

How to add auth to your Apple app in order to be listed in the Apple Store in 2025

Learn Apple’s 2025 App Store authentication requirements and see how to implement Sign in with Apple and other social logins using WorkOS AuthKit with OAuth 2.0 PKCE in your iOS app.

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, 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 with a hosted login and OAuth 2.0 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

  • Activate AuthKit in your WorkOS Dashboard 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.

When users sign out of their application, they will be redirected to your app’s 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.

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”.

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 docs.

You can also add passwordless authentication, email/password authentication, or passkeys.

6. Build the OAuth Authorization URL & start the authentication flow

Your app will open the WorkOS authorize endpoint 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, 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 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 (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.

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.