Open Closed

React-Native Tiered Project #9786


User avatar
0
gthompson2005 created

I am working on adding a mobile app utilizing react-native to my project. To test this prior to fully integrating, I used ABP Studio to create a new tiered project to test with. I adjusted the following:

  1. appsettings for both Identity(Auth) and HostAPI projects for IP Addresses from localhost to my devices local IP 192.16X.X.X.
  2. Added the suggested(documented) setting to disable transport security for OpenId
  3. Added the redirect url's to both the appsettings and to the OpenID App table
  4. Added the various urls to CORS to make sure all was covered
  5. Updated Environment in react-native to reflect the IP's to match

I was able to get the android emulator to load the project up, click login on the home page and redirect me to the Auth Server login. But it would fail on the return due to the 192.16X.X.X not matching the app url of the mobile device for whatever reason it was submitting as 10. instead of my specified 192. IP address.

So I adjusted the following.

  1. Updated the Environment file to have the below code
  2. Updated the appsettings and redirects etc to use 10.0.2.2 for issuer etc.

After changing these, I was able to get a successful code response, but the redirect was still coming back as 192.16X.X.X and there for the login on the mobile app return to the home screen as if the user was not authenticated and present the login button vs other options for standard features included.

At this point, I believe I have followed everything in the tutorial on this topic, I have a successful authentication loop occurring from mobile to Auth back to mobile. I by no means am an react-native expert so I consider this a learning activity at this point. What could I potentially be missing? I've rebuilt this twice using a ABP Studio generated project. I'm sure this is something simple that I've missed.

Environment.ts update: const yourIP = '10.0.2.2'; const apiUrl = http://${yourIP}:44359; const issuerUrl = http://${yourIP}:44322; const dev = { apiUrl, appUrl: exp://${yourIP}:19000, oAuthConfig: { issuer: issuerUrl, clientId: 'New2_Mobile', scope: 'offline_access New2', }, localization: { defaultResourceName: 'New2', }, } as Environment;

Here is the Auth server response to the clicking of the login button and the browser login event. [20:32:42 INF] The authorization response was successfully returned to 'exp://10.0.2.2:19000' using the query response mode: { "code": "[redacted]", "state": "4mGnTeKDTO", "iss": "http://10.0.2.2:44322/", "culture": "en", "ui-culture": "en" }. [20:32:42 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessQueryResponse. [20:32:42 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was marked as handled by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessQueryResponse. [20:32:42 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ApplyAuthorizationResponse1[[OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext, OpenIddict.Server, Version=6.4.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. [20:32:42 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was marked as handled by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ApplyAuthorizationResponse1[[OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext, OpenIddict.Server, Version=6.4.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. [20:32:42 INF] Executed action Volo.Abp.OpenIddict.Controllers.AuthorizeController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore) in 294.8017ms [20:32:42 INF] Executed endpoint 'Volo.Abp.OpenIddict.Controllers.AuthorizeController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore)' [20:32:42 INF] Request finished HTTP/1.1 GET http://10.0.2.2:44322/connect/authorize?code_challenge=xq93uUcSpC3iTHaU0pF1JAgT8WqNySU2dDGPOS209qI&code_challenge_method=S256&redirect_uri=exp%3A%2F%2F10.0.2.2%3A19000&client_id=New2_Mobile&response_type=code&state=4mGnTeKDTO&scope=offline_access+New2 - 302 0 null 607.4527ms


8 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    Based on your description and the official ABP documentation for React Native integration, here are the key points and steps to ensure successful authentication and token handling in a tiered ABP project with React Native:

    1. Localhost vs Emulator IPs:

      • For Android emulators, 10.0.2.2 is used to access the host machine's localhost.
      • All backend URLs (API, AuthServer, issuer, etc.) in both your backend configuration and your React Native Environment.ts must consistently use 10.0.2.2 and the correct ports.
    2. Redirect URI Consistency:

      • The redirect_uri registered in your OpenIddict client configuration (in the database and appsettings) must exactly match the one used in your React Native app (exp://10.0.2.2:19000).
      • Any mismatch (e.g., using your device's real IP or localhost instead of 10.0.2.2) will cause the authentication to fail or not complete properly.
    3. OpenIddict HTTPS Restriction:

      • During development, disable HTTPS-only restrictions in OpenIddict, as emulators and physical devices may not trust self-signed certificates.
    4. CORS and Allowed Redirects:

      • Ensure that all possible origins and redirect URIs (exp://10.0.2.2:19000, etc.) are included in your CORS and OpenIddict allowed redirect URIs.
    5. React Native App URL:

      • The appUrl in your Environment.ts should match the redirect URI used in the OAuth flow.
    6. Token Handling in React Native:

      • After a successful login, ensure your React Native app is correctly handling the OAuth redirect and extracting the authorization code or token from the URL.
      • If the app returns to the login screen after authentication, it may not be storing or using the access token properly. Double-check your authentication callback handling.
    7. Debugging Tips:

      • Use logging in your React Native app to verify that the authentication callback is received and that tokens are being stored.
      • Check the network traffic to ensure the token exchange is happening as expected.
    8. Common Pitfall:

      • If the AuthServer logs show a successful authorization response but your app does not recognize the login, the issue is almost always in the React Native app's handling of the OAuth redirect and token storage.

    Summary of what to check/fix:

    • All URLs (issuer, API, redirect) must use 10.0.2.2 and the correct port.
    • The redirect URI in OpenIddict and your app must match exactly.
    • Ensure your React Native app is handling the OAuth redirect and storing the access token.
    • Disable HTTPS-only in OpenIddict for development.
    • All CORS and allowed redirect URIs must be set for 10.0.2.2.

    For more details and troubleshooting, refer to the official documentation:

    Sources:


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    gthompson2005 created

    The AI response outlines everything I have done at this moment. Would request further guidance.

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello,

    Thank you for providing detailed information about your problem.

    If you are sure that the IP you configured is correct and the react native app is successfully responded, the problem might be on the backend side once you try to authenticate the user. For this reason, could you share the backend logs regarding the authentication process?

    Thank you for your patience and cooperation.

  • User Avatar
    0
    gthompson2005 created

    Here is the Identity/Auth Server Log: 2025-08-18 20:32:42.304 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+ResolveHostSignInProperties. 2025-08-18 20:32:42.305 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+ValidateSignInDemand. 2025-08-18 20:32:42.305 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+RedeemTokenEntry. 2025-08-18 20:32:42.305 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+RestoreInternalClaims. 2025-08-18 20:32:42.306 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+AttachHostProperties. 2025-08-18 20:32:42.306 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+AttachDefaultScopes. 2025-08-18 20:32:42.306 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+AttachDefaultPresenters. 2025-08-18 20:32:42.306 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+InferResources. 2025-08-18 20:32:42.306 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+EvaluateGeneratedTokens. 2025-08-18 20:32:42.306 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+AttachAuthorization. 2025-08-18 20:32:42.309 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+PrepareAuthorizationCodePrincipal. 2025-08-18 20:32:42.315 -04:00 [DBG] Creating identity session for session id: 66aa238b-b694-49ed-93e0-3a957abdb9a5, device: OAuth, user id: b0720c2d-b561-bf72-6f7c-3a1bcc7809ea, tenant id: , client id: New2_Mobile 2025-08-18 20:32:42.325 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by Volo.Abp.Account.Web.Pages.Account.OpenIddictCreateIdentitySession. 2025-08-18 20:32:42.325 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+AttachCustomSignInParameters. 2025-08-18 20:32:42.326 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+GenerateTokenContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Protection+AttachSecurityCredentials. 2025-08-18 20:32:42.356 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+GenerateTokenContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Protection+CreateTokenEntry. 2025-08-18 20:32:42.360 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+GenerateTokenContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Protection+GenerateIdentityModelToken. 2025-08-18 20:32:42.400 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+GenerateTokenContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Protection+AttachTokenPayload. 2025-08-18 20:32:42.400 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+GenerateAuthorizationCode. 2025-08-18 20:32:42.400 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+BeautifyGeneratedTokens. 2025-08-18 20:32:42.400 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+AttachSignInParameters. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+AttachRedirectUri. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+InferResponseMode. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+AttachResponseState. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+AttachIssuer. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by Volo.Abp.OpenIddict.Globalization.AttachCultureInfo. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+AttachHttpResponseCode1[[OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext, OpenIddict.Server, Version=6.4.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+AttachCacheControlHeader1[[OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext, OpenIddict.Server, Version=6.4.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessSelfRedirection. 2025-08-18 20:32:42.401 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessFormPostResponse. 2025-08-18 20:32:42.401 -04:00 [INF] The authorization response was successfully returned to 'exp://10.0.2.2:19000' using the query response mode: { "code": "[redacted]", "state": "4mGnTeKDTO", "iss": "http://10.0.2.2:44322/", "culture": "en", "ui-culture": "en" }. 2025-08-18 20:32:42.402 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessQueryResponse. 2025-08-18 20:32:42.402 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was marked as handled by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessQueryResponse. 2025-08-18 20:32:42.402 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ApplyAuthorizationResponse1[[OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext, OpenIddict.Server, Version=6.4.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. 2025-08-18 20:32:42.402 -04:00 [DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was marked as handled by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ApplyAuthorizationResponse1[[OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext, OpenIddict.Server, Version=6.4.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. 2025-08-18 20:32:42.402 -04:00 [INF] Executed action Volo.Abp.OpenIddict.Controllers.AuthorizeController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore) in 294.8017ms 2025-08-18 20:32:42.402 -04:00 [INF] Executed endpoint 'Volo.Abp.OpenIddict.Controllers.AuthorizeController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore)' 2025-08-18 20:32:42.410 -04:00 [INF] Request finished HTTP/1.1 GET http://10.0.2.2:44322/connect/authorize?code_challenge=xq93uUcSpC3iTHaU0pF1JAgT8WqNySU2dDGPOS209qI&code_challenge_method=S256&redirect_uri=exp%3A%2F%2F10.0.2.2%3A19000&client_id=New2_Mobile&response_type=code&state=4mGnTeKDTO&scope=offline_access+New2 - 302 0 null 607.4527ms

    Here is my Environment:

    import { Environment } from '@new2/models';

    const yourIP = '10.0.2.2'; // See the docs https://docs.abp.io/en/abp/latest/Getting-Started-React-Native?Tiered=No const apiUrl = http://${yourIP}:44359; const issuerUrl = http://${yourIP}:44322; const dev = { apiUrl, appUrl: exp://${yourIP}:19000, oAuthConfig: { issuer: issuerUrl, clientId: 'New2_Mobile', scope: 'offline_access New2', }, localization: { defaultResourceName: 'New2', }, } as Environment;

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello again, Thank you for providing logs. As far as I see, there is no problem on backend side. I suspect the gateway configurations declared in gateways/mobile/MyProjectName.MobileGateway/appsettings.json

    Can you try updating the ClusterId for AbpApi route to AuthServer that may solve your problem?

    {
      "App": {
        "CorsOrigins": "",
        "HealthCheckUrl": "/health-status"
      },
      "AuthServer": {
        "SwaggerClientId": "SwaggerTestUI"
      },
      "ElasticSearch": {
        "IsLoggingEnabled": true,
        "Url": "http://localhost:9200"
      },
      "Swagger": {
        "IsEnabled": true
      },
      "ReverseProxy": {
        "Routes": {
          "AbpApi": {
            "ClusterId": "AuthServer", // You may need to check here
            "Match": {  
              "Path": "/api/abp/{**catch-all}"
            }
          },
          "SettingManagement": {
            "ClusterId": "Administration",
            "Match": {
              "Path": "/api/setting-management/{**catch-all}"
            }
          },
          "FeatureManagement": {
            "ClusterId": "Administration",
            "Match": {
              "Path": "/api/feature-management/{**catch-all}"
            }
          },
          "PermissionManagement": {
            "ClusterId": "Administration",
            "Match": {
              "Path": "/api/permission-management/{**catch-all}"
            }
          },
          "Saas": {
            "ClusterId": "Saas",
            "Match": {
              "Path": "/api/saas/{**catch-all}"
            }
          },
          "SaasSwagger": {
            "ClusterId": "Saas",
            "Match": {
              "Path": "/swagger-json/Saas/swagger/v1/swagger.json"
            },
            "Transforms": [
              { "PathRemovePrefix": "/swagger-json/Saas" }
            ]
          },
          "OpenIddict": {
            "ClusterId": "Identity",
            "Match": {
              "Path": "/api/openiddict/{**catch-all}"
            },
            "AuthorizationPolicy": "Anonymous"  
          },
          "AdministrationSwagger": {
            "ClusterId": "Administration",
            "Match": {
              "Path": "/swagger-json/Administration/swagger/v1/swagger.json"
            },
            "Transforms": [
              { "PathRemovePrefix": "/swagger-json/Administration" }
            ]
          },
          "Account": {
            "ClusterId": "AuthServer",
            "Match": {
              "Path": "/api/account/{**catch-all}"
            }
          },
          "AccountAdmin": {
            "ClusterId": "AuthServer",
            "Match": {
              "Path": "/api/account-admin/{**catch-all}"
            }
          },
          "AuthServerSwagger": {
            "ClusterId": "AuthServer",
            "Match": {
              "Path": "/swagger-json/AuthServer/swagger/v1/swagger.json"
            },
            "Transforms": [
              { "PathRemovePrefix": "/swagger-json/AuthServer" }
            ]
          },
          "Identity": {
            "ClusterId": "Identity",
            "Match": {
              "Path": "/api/identity/{**catch-all}"
            },
            "AuthorizationPolicy": "Anonymous"  
          },
          "IdentitySwagger": {
            "ClusterId": "Identity",
            "Match": {
              "Path": "/swagger-json/Identity/swagger/v1/swagger.json"
            },
            "Transforms": [
              { "PathRemovePrefix": "/swagger-json/Identity" }
            ]
          }
        },
        "Clusters": {
          "AuthServer": {
            "Destinations": {
              "AuthServer": {
                "Address": "http://yourIP:44392/"
              }
            }
          },
          "Administration": {
            "Destinations": {
              "Administration": {
                "Address": "http://yourIP:44300/"
              }
            }
          },
          "Saas": {
            "Destinations": {
              "Saas": {
                "Address": "http://yourIP:44301/"
              }
            }
          },
          "Identity": {
            "Destinations": {
              "Identity": {
                "Address": "http://yourIP:44381/"
              }
            }
          }
        }
      }
    }
    

    If this does not solve your problem, you can send me a minimal reproducible example to investigate further. Here is my email address: sumeyye.kurtulus@volosoft.com.

  • User Avatar
    0
    gthompson2005 created

    Sumeyye

    I should clarify that I am using a Tiered Blazor project, not a microservice. I don't have a Gateway/Mobile project. Looks like that comes when you are doing a microservice project but I may be wrong.

    I will send over the base project, Appreciate your support on this.

    Thank you

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello again,

    Thank you for providing extra details. I have duplicated the same problem on my end. I am investigating further and will be getting back to you soon.

    Thank you again for your cooperation.

  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello, We will be fixing this problem for the next studio release where you can follow from this link https://abp.io/docs/latest/studio/release-notes

    Until we release a fix, you can follow these steps to make your application work. I will also be sending a sample project having the same fixes.

    • Update your Environment.ts to separate the authentication flow from the host application as follows
    // ...
    // Separate the API and AuthServer URLs
    const apiUrl = `http://${yourIP}:44331`;
    const oAuthIssuer = `http://${yourIP}:44327`;
    
    const dev = {
      apiUrl,
      appUrl: `exp://${yourIP}:19000`,
      oAuthConfig: {
        issuer: oAuthIssuer,
        clientId: 'Ticket9786_Mobile',
        scope: 'offline_access Ticket9786',
      },
      localization: {
        defaultResourceName: 'Ticket9786',
      },
    } as Environment;
    
    const prod = {
      apiUrl,
      appUrl: `exp://${yourIP}:19000`,
      oAuthConfig: {
        issuer: oAuthIssuer,
        clientId: 'Ticket9786_Mobile',
        scope: 'offline_access Ticket9786',
      },
      localization: {
        defaultResourceName: 'Ticket9786',
      },
    } as Environment;
    // ...
    
    • Replace your UseAuthAndTokenExchange.ts as follows
    import * as WebBrowser from 'expo-web-browser';
    
    import { store } from '../store';
    import AppActions from '../store/actions/AppActions';
    import PersistentStorageActions from '../store/actions/PersistentStorageActions';
    import { getEnvVars } from '../../Environment';
    import { makeRedirectUri } from 'expo-auth-session';
    
    const {
      oAuthConfig: { issuer, clientId, scope },
    } = getEnvVars();
    
    const useAuthAndTokenExchange = navigation => {
      const handleAuthentication = async () => {
        try {
          // For tiered architecture: open AuthServer in browser
          // AuthServer will handle OAuth and redirect back to React Native
    
          const redirectUri = makeRedirectUri();
    
          const authUrl =
            `${issuer}/connect/authorize?` +
            `client_id=${clientId}&` +
            `redirect_uri=${encodeURIComponent(redirectUri)}&` +
            `response_type=code&` +
            `scope=${encodeURIComponent(scope)}&` +
            `state=${Math.random().toString(36).substring(7)}`;
    
          const result = await WebBrowser.openAuthSessionAsync(authUrl, redirectUri);
    
          if (result.type === 'success') {
            // Parse the redirect URL to get authentication data
            const url = new URL(result.url);
            const code = url.searchParams.get('code');
    
            if (code) {
              // For tiered architecture, we need to establish the authenticated session
              // This could be by exchanging the code for a token, or by getting user context
    
              // Option 1: Exchange code for token (if the app needs to make API calls)
              try {
                const tokenEndpoint = `${issuer}/connect/token`;
                const tokenResponse = await fetch(tokenEndpoint, {
                  method: 'POST',
                  headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                  },
                  body: new URLSearchParams({
                    grant_type: 'authorization_code',
                    client_id: clientId,
                    code: code,
                    redirect_uri: redirectUri,
                  }).toString(),
                });
    
                if (tokenResponse.ok) {
                  const tokenData = await tokenResponse.json();
    
                  // Store the token for future API calls
                  store.dispatch(
                    PersistentStorageActions.setToken({
                      token_type: tokenData.token_type || 'Bearer',
                      access_token: tokenData.access_token,
                      refresh_token: tokenData.refresh_token,
                      expire_time: new Date().valueOf() + tokenData.expires_in * 1000 || 0,
                      scope: tokenData.scope,
                    }),
                  );
    
                  // After establishing the session, fetch app config to get current user
                  store.dispatch(AppActions.fetchAppConfigAsync({ showLoading: false }));
                  navigation.navigate('Home');
                } else {
                  console.error('💥 Failed to establish authenticated session');
                }
              } catch (error) {
                console.error('💥 Error establishing authenticated session:', error);
              }
            } else {
              console.error('💥 No authorization code in redirect URL');
              console.error('💥 Full redirect URL:', result.url);
            }
          } else if (result.type === 'cancel') {
            console.log('🚀 ~ Auth cancelled by user');
          } else {
            console.log('🚀 ~ Auth result type:', result.type);
          }
        } catch (error) {
          console.error('💥 Error in authentication flow:', error);
        }
      };
    
      return { handleAuthentication };
    };
    
    export default useAuthAndTokenExchange;
    
    
    • Update your db migrator to use your IP instead just for the mobile client, then rerun the migration.
    // src/YourProject.DbMigrator/appsettings.json
    {
      "ConnectionStrings": {
        "Default": "mongodb://localhost:27017/Ticket9786"
      },
      "Redis": {
        "Configuration": "127.0.0.1"
      },
      "OpenIddict": {
        "Applications": {
          // ...
          },
          "Ticket9786_Mobile": {
            "ClientId": "Ticket9786_Mobile",
            "RootUrl": "exp://192.168.1.39:19000"
          },
          "Ticket9786_BlazorServer": {
            "ClientId": "Ticket9786_BlazorServer",
            "ClientSecret": "1q2w3e*",
            "RootUrl": "https://localhost:44385"
          },
          "Ticket9786_Swagger": {
            "ClientId": "Ticket9786_Swagger",
            "RootUrl": "https://localhost:44331/"
          }
        }
      }
    }
    
    
    • Add this configuration to the preconfigure services in auth server module
     #if DEBUG
            PreConfigure<OpenIddictServerBuilder>(options =>
            {
                options.UseAspNetCore()
                    .DisableTransportSecurityRequirement();
            });
     #endif
    
    • I suggest you to use Kestrel configuration for the development phase, so you can update the development settings as follows
    // src/YourProject.AuthServer/appsettings.Development.json
    {
      "Kestrel": {
        "Endpoints": {
          "Http": {
            "Url": "http://0.0.0.0:44327"
          }
        }
      }
    }
    
    // src/YourProject.HttpApi.Host/appsettings.Development.json
    {
      "Kestrel": {
        "Endpoints": {
          "Http": {
            "Url": "http://0.0.0.0:44331"
          }
        }
      },
      "AuthServer": {
        "Authority": "http://192.168.1.39:44327",
        "MetaAddress": "http://192.168.1.39:44327",
        "RequireHttpsMetadata": false,
        "Audience": "Ticket9786"
      }
    }
    

    You can let us know if you need further assistance. Thank you for your cooperation.

Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 12, 2025, 10:20