MaikuB / flutter_appauth

A Flutter wrapper for AppAuth iOS and Android SDKs
273 stars 246 forks source link

`flutter_appauth` doesn't back to app with localhost callback url #383

Closed Asncodes-80 closed 1 year ago

Asncodes-80 commented 1 year ago

Hi to Flutter app auth team. I have used from this plugin in flutter latest version. When i used from that with some conditions, callback url doesn't cause back to my application.

Result in url:

Screenshot 1401-08-05 at 2 28 59 PM

What i did in my application:

At first i should say, i used Strava api for authentication and getting authorization code. In that Strava developer panel, you can set only an address without any scheme before of that for callback url, like localhost. With localhost or any things I will get authorization code in url perfectly, But my main problem is return of callback address to app.

dependency:

module:
  androidX: true
...
  flutter_appauth: ^4.2.1

Main functionality

      // Instance of web auth in app authn
      FlutterAppAuth appAuth = const FlutterAppAuth();

      // Make Strava Authorization Request
      late AuthorizationRequest stravaOAuth = AuthorizationRequest(
        dotenv.env["STRAVA_CLIENT_ID"].toString(),
        clientRedirectionURL,
        preferEphemeralSession: true, // Auto admit from iOS System for login
        scopes: <String>[stravaActivityScope],
        allowInsecureConnections: true,
        serviceConfiguration: const AuthorizationServiceConfiguration(
          authorizationEndpoint: "$stravaBaseURL/oauth/authorize",
          tokenEndpoint: tokenEndpointURL,
          endSessionEndpoint: clientRedirectionURL,
        ),
      );

      // Parse and perform web auth
      AuthorizationResponse? stravaAuthResult =
          await appAuth.authorize(stravaOAuth);

For Android in android/app/build.gradle:

    defaultConfig {
        minSdkVersion 24
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        manifestPlaceholders += [
            "appAuthRedirectScheme": "localhost",
            "appAuthRedirectScheme": "http"
        ]
    }

In AndroidManifest.xml

<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
            <intent-filter android:autoVerify="true">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="http" android:host="localhost" />
</intent-filter>

For iOS in info.plist:

    <string>CFBundleURLTypes</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLName</key>
            <string>localhost</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>http</string>
            </array>
        </dict>
    </array>

For more information about my problem with flutter_appauth you can read my issue in Strava Google group system.

Dahkenangnon commented 1 year ago

Hi @Asncodes-80

In short your problem is related to callback uri.

You should understand how the authorization code flow (in Open ID Connect & OAuth, world) work:

auth-sequence-auth-code-pkce

By the side, your Identity Provider, have certainly an option "register a native app or mobile", or again someting like that. This should allow you to register some redirect_uri /callback uri like com.mydomain.myapp://login-callback

As you can notice, this type of redirect_uri is a custom scheme and should make you app capable to handle incoming link starting with this url scheme.

So pratically, I suggest you to:

  1. Register a correct and native friendly callback uri like one I give above: com.mydomain.myapp://login-callback
  2. Then in your android/app/build.gradle

    defaultConfig {
        // other config
    
        manifestPlaceholders += [
                'appAuthRedirectScheme': 'com.mydomain.myapp'
        ]
    }
  3. Make sure to configure also your info.plist accordingly
  4. Now, you should be able to get from the authorization server, the authorization code then exchange it for access token in order to call your apis

In the case your identify provider don't support native callback uri ou custom scheme in redirect_uri, you can a bridge server between your authorization server and your mobile application:

  1. You configure your authorization server to use as callack uri something like: https://auth.mydomain.com/redirect/my-mobileapp
  2. https://auth.mydomain.com/redirect/my-mobileapp should be able to get an authorization code and send it to your app through deeplinking or custom scheme
  3. In your FlutterAppAuth instance, you must use then as redirect_uri: https://auth.mydomain.com/redirect/my-mobileapp
  4. How it will work ?
    • You mobile request for authorization request (with FlutterAppAuth), when it time to exchance code, the authorization code will contact not directly your mobile app but you authorization bridge server which have the responsability to send the code to your app. Then the process can continue to get retrieve access token.

You can also check out this auth0 tutorial: https://github.com/auth0-blog/flutter-authentication

Thank

adrianvintu commented 1 year ago

@Asncodes-80 You need to replace localhost with 10.0.02 like so

final String _discoveryUrl =
      'http://localhost:8080/realms/myrealm/.well-known/openid-configuration'.replaceAll('localhost', '10.0.2.2');