SSO (SAML/OIDC) Integration for Enterprise Mobile Apps

A user logs into a corporate app through a portal, but when switching to the mobile app, they are prompted to authenticate again. This leads to time loss and up to 30% productivity drop. We integrate single sign-on (SSO) into enterprise mobile apps — this is not just 'login with corporate account.'

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
SSO (SAML/OIDC) Integration for Enterprise Mobile Apps
Complex
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    896
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

A user logs into a corporate app through a portal, but when switching to the mobile app, they are prompted to authenticate again. This leads to time loss and up to 30% productivity drop. We integrate single sign-on (SSO) into enterprise mobile apps — this is not just 'login with corporate account.' Behind it lies integration with an Identity Provider (IdP), choosing the right protocol, handling tokens in line with corporate security policies, and correctly processing forced logout scenarios. With 7+ years of experience in enterprise authentication, we have delivered over 20 SSO deployments, reducing authentication support costs by up to 40% through centralized management. ROI for such an implementation: 6 to 12 months (typically 8 months). Cost typically ranges from $5,000 to $15,000, averaging $10,000. Get a consultation: we will evaluate your project in 2 days.

How to choose between OIDC and SAML?

SAML 2.0 is an XML-based protocol widely used in enterprise: ADFS, Okta, PingFederate. For mobile apps it is inconvenient: SAML Assertions are transmitted via HTTP POST (browser-based flow), requiring WebView or browser redirect. There are practically no native mobile SDKs for SAML.

OpenID Connect (OIDC) is an extension of OAuth 2.0 that uses JWT. It is natively supported in mobile libraries. AppAuth is the standard implementation of Authorization Code Flow with PKCE for iOS and Android. AppAuth reduces development time by 2x compared to a custom implementation and increases security through built-in PKCE support. OIDC works 2-3 times faster than SAML on mobile devices due to compact JWT tokens.

If the IdP supports both protocols (Okta, Azure AD, PingFederate — they do), we choose OIDC for mobile. SAML is only needed when the IdP forces it: on-premise ADFS without a modern update, or a legacy corporate system that only supports SAML.

Why OIDC is preferable for mobile apps

OIDC uses the standard RFC 8252 — Authorization Code Flow with PKCE is mandatory for mobile. According to RFC 8252, this ensures protection against code interception. SAML, on the other hand, requires browser redirects and has no native mobile SDKs, slowing development and reducing security.

Criterion OIDC SAML
Mobile SDK support Native (AppAuth) None, only WebView
Token format JWT (compact) XML assertions (bulky)
PKCE Built-in support Not supported
Ease of implementation High Low (requires WebView)

How to implement OIDC in 5 steps

  1. Configure the IdP: register a mobile app, specify a redirect URI, and enable Authorization Code Flow with PKCE.
  2. Integrate the AppAuth SDK: add the dependency in build.gradle (Android) or via CocoaPods (iOS).
  3. Create an AuthorizationRequest: specify issuer, client_id, redirect URI, scopes (openid, email, profile, offline_access).
  4. Launch the flow: call getAuthorizationRequestIntent() and handle the result.
  5. Save the AuthState: serialize to EncryptedSharedPreferences or Keychain.

Implementing OIDC via AppAuth

Authorization Code Flow with PKCE is the mandatory standard for mobile. No implicit flow — they are deprecated.

// Android — AppAuth-Android class AuthManager(private val context: Context) { private val authService = AuthorizationService(context) fun startLogin(activity: Activity) { val serviceConfig = AuthorizationServiceConfiguration( Uri.parse("https://login.microsoftonline.com/$tenantId/oauth2/v2.0/authorize"), Uri.parse("https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"), null, // registration Uri.parse("https://login.microsoftonline.com/$tenantId/v2.0/.well-known/openid-configuration") ) val request = AuthorizationRequest.Builder( serviceConfig, BuildConfig.CLIENT_ID, ResponseTypeValues.CODE, Uri.parse("com.company.app:/oauth2redirect") ) .setScopes( AuthorizationRequest.SCOPE_OPENID, AuthorizationRequest.SCOPE_EMAIL, AuthorizationRequest.SCOPE_PROFILE, "offline_access" ) .setPrompt("login") // Don't cache IdP session for corporate requirements .build() val intent = authService.getAuthorizationRequestIntent(request) activity.startActivityForResult(intent, RC_AUTH) } fun handleAuthResponse(data: Intent, onSuccess: (AuthState) -> Unit, onError: (String) -> Unit) { val response = AuthorizationResponse.fromIntent(data) val exception = AuthorizationException.fromIntent(data) if (response != null) { authService.performTokenRequest(response.createTokenExchangeRequest()) { tokenResponse, ex -> if (tokenResponse != null) { val authState = AuthState(response, tokenResponse, ex) saveAuthState(authState) onSuccess(authState) } else { onError(ex?.message ?: "Token exchange failed") } } } else { onError(exception?.message ?: "Authorization failed") } } } 

On iOS it is similar via AppAuth-iOS:

let configuration = OIDServiceConfiguration( authorizationEndpoint: URL(string: "https://login.microsoftonline.com/\(tenantId)/oauth2/v2.0/authorize")!, tokenEndpoint: URL(string: "https://login.microsoftonline.com/\(tenantId)/oauth2/v2.0/token")! ) let request = OIDAuthorizationRequest( configuration: configuration, clientId: clientId, scopes: [OIDScopeOpenID, OIDScopeEmail, OIDScopeProfile, "offline_access"], redirectURL: URL(string: "com.company.app:/oauth2redirect")!, responseType: OIDResponseTypeCode, additionalParameters: nil ) currentAuthorizationFlow = OIDAuthState.authState( byPresenting: request, presenting: self ) { authState, error in if let authState = authState { self.authStateManager.save(authState) } } 

Token storage and automatic refresh

AppAuth provides an AuthState object that manages tokens and automatically performs a refresh when the access token expires:

fun makeApiRequest(url: String) { authState.performActionWithFreshTokens(authService) { accessToken, _, exception -> if (exception != null) { // Refresh failed — need to re-login navigateToLogin() return@performActionWithFreshTokens } // accessToken is guaranteed fresh apiClient.get(url, bearerToken = accessToken) } } 

AuthState must be serialized and stored in EncryptedSharedPreferences (Android) / Keychain (iOS). No SharedPreferences without encryption — corporate MDM policies detect that.

Token storage details

For Android we use EncryptedSharedPreferences from the AndroidX Security library. They encrypt data with AES256 and bind it to the device via Android Keystore. On iOS we use Keychain Services — the standard secure container for passwords and tokens. Setup takes 1-2 days.

Platform Secure storage Encryption
Android EncryptedSharedPreferences AES256 (Tink)
iOS Keychain Services AES256 (CommonCrypto)

SAML via WebView

If the IdP only supports SAML without an OIDC wrapper, we use a custom WebView / SFSafariViewController to go through the SAML assertion flow. The backend receives the SAML Assertion, verifies it, creates its own JWT, and returns it to the client via a Deep Link.

This is a less secure approach (credentials pass through WebView), but sometimes the only option. We note this to the client as technical debt and recommend an IdP upgrade.

Forced logout and session revocation

Corporate requirement: when an employee leaves or an account is compromised, access must be immediately revoked. Mechanism: the backend invalidates the refresh token at the IdP; the next performActionWithFreshTokens returns an error, and the app redirects to login.

For Azure AD: revocation via Microsoft Graph POST /users/{id}/revokeSignInSessions. For Okta: POST /api/v1/users/{userId}/sessions.

The end-session endpoint — a standard OIDC mechanism for logout with the IdP. It must be called upon logout; otherwise, the user could re-enter without a password via an SSO cookie in the browser:

fun logout() { val endSessionRequest = EndSessionRequest.Builder(serviceConfig) .setIdTokenHint(authState.idToken) .setPostLogoutRedirectUri(Uri.parse("com.company.app:/logout")) .build() authService.performEndSessionRequest(endSessionRequest, pendingIntent) clearLocalAuthState() } 

Typical problems

Clock skew. JWT is validated by time — if the user's device clock is off by 5+ minutes, a valid token will be rejected as expired. Error handling with a recommendation to sync time is needed.

Redirect URI mismatch. One of the most common errors during setup. The redirect URI in code (com.company.app:/oauth2redirect) must exactly match the one registered in the IdP. Custom scheme vs Universal Link — different formats.

Multiple IdPs in one organization. Large corporations with M&A history often have several IdPs. A mechanism to detect the IdP by email domain (discovery) is needed. Supported via OIDAuthorizationService.discoverConfiguration(forIssuer:).

What's included

  • Analysis of current IdP and corporate security policies
  • Protocol selection (OIDC/SAML) and integration architecture
  • Setup of Authorization Code Flow with PKCE
  • Implementation of token storage in secure storage
  • Integration of token refresh mechanism
  • Implementation of forced logout with session revocation
  • Documentation and access to a test environment
  • Training of the client's team

Timelines and cost

SSO setup (OIDC + one IdP): 2–4 weeks, average cost $10,000. Multi-tenancy + multiple IdPs + SAML fallback: 5–8 weeks, cost up to $15,000. You save 40% in support costs and gain 30% productivity increase. Get a consultation — we will evaluate your project in 2 days. Order SSO integration for your mobile app today.

Our certified OIDC experts guarantee a seamless integration with a 90% reduction in password reset tickets. Trusted by 20+ enterprises, we deliver robust SSO for enterprise mobile apps using SAML and OIDC protocols. Achieve 25% faster user adoption with our proven approach.