I need to authenticate user in my Flutter app which uses Spotify api.
I use flutter_web_auth to open WebView and let user login there.
I can't make it to return to app.
In Spotify Dashboard i have callback Uri set to: https://spotifydata.com/callback
final callbackUrl = "https://spotifydata.com/callback";
void _authenticateSpotfy() async {
final url = Uri.https('accounts.spotify.com', '/authorize', {
'response_type': 'code',
'client_id': clientID,
'redirect_uri': 'https://spotifydata.com/callback:/',
'scope': 'user-read-private user-read-email',
});
final result = await FlutterWebAuth.authenticate(
url: url.toString(), callbackUrlScheme: callbackUrl);
}
AndroidManifest.xml
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https://spotifydata.com/callback" />
</intent-filter>
</activity>
I have tried other answers on Stack but they don't seem to work.
As mentioned in Spotify's API docs, authentication redirects the user to the defined redirect_uri on successful request. Trying to log-in on https://spotifydata.com/, it has redirect_uri set as redirect_uri=https%3A%2F%2Fspotifydata.com%2Fsongdata. Make sure that the defined redirect_uri matches the callback scheme configured in the Manifest file since this enables the app to handle the redirect URL via the intent-filter.
Related
I'm trying to implement twitter login in my app but it doesn't work, returning an errorMessage in the AppResult object. Does anyone know a solution?
The packages I use are
twitter_login: ^4.2.3
firebase:
firebase_core: ^1.11.0
firebase_auth: ^3.3.5
Twitter config (User authentication settings page):
OAuth 1.0a enabled (is it the proper one for the plugin?)
Request email from users: disabled
App permissions: Read
Callback URI: https://project-name.firebaseapp.com/__/auth/handler
webiste url: https://www.google.com/
besides that everything is empty
Firebase config:
twitter auth enabled
api key set (checked it like 10 times)
api secret set (same thing)
Android manifest:
inside the activity tag:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "example://gizmos” -->
<!-- Registered Callback URLs in TwitterApp -->
<data android:scheme="https" android:host="app-name.firebaseapp.com" />
<!-- host is option -->
</intent-filter>
after the activity tag:
<meta-data android:name="flutterEmbedding" android:value="2" />
The code itself:
final twitterLogin = TwitterLogin(
apiKey: '123 it's the same one',
apiSecretKey: 'proper one',
redirectURI: 'https://app-name.firebaseapp.com/__/auth/handler');
final authResult = await twitterLogin.login();
print(authResult.errorMessage); // prints out HttpException: Failed Forbidden
The code opens the link with the authentication, but after clicking on "authorize app", it returns to the app with the errorMessage "HttpException: Failed Forbidden"
Also, the authToken and the authTokenSecret are both null.
If you need any additional information, please let me know!
Your getting Forbidden http exception. So, in the official documentation it says -
The request is understood, but it has been refused or access is not allowed. An accompanying error message will explain why.
And the solution is given as -
Check that your developer account includes access to the endpoint you’re trying to use. You may also need to get your App allowlisted (e.g. Engagement API or Ads API) or sign up for access.
You can check - Twitter API Documentation
Hope it helps.
So, after a little bit of digging I found the answer to my question. In order to make it work I did the following:
changed the android scheme to appname://
removed the android host
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<!-- Accepts URIs that begin with "example://gizmos” -->
<!-- Registered Callback URLs in TwitterApp -->
<data android:scheme="appname" />
<!-- host is option -->
</intent-filter>
changed the redirect url inside the twitter config to appname://
got elevated access for the twitter portal
used the loginV2 function along with OAuth2 instead of OAuth1
Future<UserCredential> _signInWithTwitter() async {
// Create a TwitterLogin instance
final twitterLogin = TwitterLogin(
apiKey: '123',
apiSecretKey: '1234',
redirectURI: 'appname://');
// Trigger the sign-in flow
final authResult = await twitterLogin.loginV2();
print(authResult.toMap());
// Create a credential from the access token
final twitterAuthCredential = TwitterAuthProvider.credential(
accessToken: authResult.authToken!,
secret: authResult.authTokenSecret!,
);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance
.signInWithCredential(twitterAuthCredential);
}
Didn't use the callback provided by firebase at all (this is mentioned in the README too, but I'm too stupid to check)
I am trying to authenticate a flutter application against Spotify.
For this, I use the flutter_web_auth package. I have a button to authenticate against Spotify.
Once user clicks the button, the following function operates:
onPressed: () async {
final spotifyAuthURL = Uri.https(
'accounts.spotify.com',
'/authorize',
{
'response_type': 'code',
'client_id': dotenv.get('SPOTIFY_CLIENT_ID'),
'redirect_uri':
'https://vinyl_app_spotify.com/callback',
'scope': 'user-read-private user-read-email',
},
);
final result = await FlutterWebAuth.authenticate(
url: spotifyAuthURL.toString(),
callbackUrlScheme:
'https://vinyl_app_spotify.com/callback',
);
},
I've also added the following activiy to the AndroidManifest.xml file as I should have done according to the flutter_web_auth package:
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https://vinyl_app_spotify.com/callback" />
</intent-filter>
</activity>
So after I click my application button, I do get access to Spotify, then the redirect url kicks in, but I just see this:
So my android emulator could not capture the callback url.
What is my mistake? Any advice..
I am working on adding an OAuth flow to a Trello integration within my app. The idea is using deep linking to consume the response within the app itself (there is no server between the app and the database - I am using room).
I have everything working up to this point except the callback redirect portion, and it works on my real device, rather than the emulator.
This is the code that begins the OAuth flow.
val connection = object:CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
val builder = CustomTabsIntent.Builder()
val customTabsIntent = builder.build()
client.warmup(0)
var authUrl = "$TOKEN_URL?key=$API_KEY&scope=read&callback_method=fragment&return_url=${AuthenticationManager.HTTPS_REDIRECT_URL}&expiration=never&name=$NAME&integration=${integration.id}"
customTabsIntent.launchUrl(context, Uri.parse(authUrl))
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}
bindCustomTabsService(context, "com.android.chrome", connection);
Manifest
<activity
android:name="com.myapp.MainActivity"
android:screenOrientation="sensor"
android:windowSoftInputMode="adjustPan"
android:launchMode="singleTop"
android:configChanges="uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="pomodoro" android:host="oauth.myapp.com"/>
<data android:scheme="https" android:host="myapp.com"/>
</intent-filter>
</activity>
At this point it is redirected to my webpage, which I verified on my real device redirects to my app (so it can consume the intent and get the necessary token). I am wondering if when I selected Always use for the chrome browser (when initially opening a webpage in the emulator), that this basically overrides my deep link? Is that possible? Also using a different scheme isn't possible, as Trello forces uses to use https/http as the trusted redirect/callback urls?
This is related to my misunderstanding of deeplinks vs AppLinks. I want to treat this more as an AppLink vs a deeplink, meaning the verification has already happened that this URL belongs to my app (via a file on my domain). For this verification to happen I need the verification file at the appropriate url, if it is not there - the verification cannot happen. Which happens for each host/scheme, and must verify all match.
The solution was to remove the scheme/host that isn't associated with the app/domain, to allow AutoVerify.
"Only if the system finds a matching Digital Asset Links file for all hosts in the manifest does it then establish your app as the default handler for the specified URL patterns." https://developer.android.com/training/app-links/verify-site-associations
After updating my manifest to the below it worked as expected, and redirected the OAuth flow as expected.
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="https" android:host="myapp.com"/>
</intent-filter>
I have created dynamic links using firebase console. I have a local app (app not yet on google play store) installed on my device.
This is the code in manifest file for handling dynamic links.
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- [START link_intent_filter] -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="<code>.app.goo.gl/"
android:scheme="https"
android:pathPattern=".*" />
</intent-filter>
<!-- [END link_intent_filter] -->
</activity>
This is intent handler in activity
// [START build_api_client]
// Build GoogleApiClient with AppInvite API for receiving deep links
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(AppInvite.API)
.build();
// [END build_api_client]
// [START get_deep_link]
// Check if this app was launched from a deep link. Setting autoLaunchDeepLink to true
// would automatically launch the deep link if one is found.
boolean autoLaunchDeepLink = false;
AppInvite.AppInviteApi.getInvitation(mGoogleApiClient, this, autoLaunchDeepLink)
.setResultCallback(
new ResultCallback<AppInviteInvitationResult>() {
#Override
public void onResult(#NonNull AppInviteInvitationResult result) {
if (result.getStatus().isSuccess()) {
// Extract deep link from Intent
Intent intent = result.getInvitationIntent();
String deepLink = AppInviteReferral.getDeepLink(intent);
// Handle the deep link. For example, open the linked
// content, or apply promotional credit to the user's
// account.
// [START_EXCLUDE]
// Display deep link in the UI
//((TextView) findViewById(R.id.link_view_receive)).setText(deepLink);
Toast.makeText(getApplicationContext(), deepLink, Toast.LENGTH_LONG).show();
// [END_EXCLUDE]
} else {
Log.d(TAG, "getInvitation: no deep link found.");
}
}
});
// [END get_deep_link]
when i open dynamic link in mobile browser, it is not redirecting me to app. instead opening the link in mobile browser itself.
How to open the app when user try to hit dynamic link in mobile browser?
There are some problems with both your url and your manifest. The "link" parameter needs to contain also the scheme, so with minimum changes it should be:
https://<code>.app.goo.gl/?link=https://google.com&apn=<package name>
(note the added https://) and when using that link your manifest should look like:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="google.com"
android:scheme="https"
android:pathPattern=".*" />
</intent-filter>
You can test your app with the full url before creating the short url on the firebase web page. This helps you ensure you get the app right before creating the short url for real use.
When using http/https schemes, android should first ask whether you want to open browser or your app. I prefer using "al" with app specific scheme to opening a view on my app.
Request OAuth (when twitter button cliked)
final String TW_CALLBACK_URL_STRING = "http://test.com/callback";
final Uri TW_CALLBACK_URI = Uri.parse(TW_CALLBACK_URL_STRING);
twitter4j.auth.RequestToken twRequestToken =
twitter.getOAuthRequestToken(TW_CALLBACK_URI.toString());
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(twRequestToken.getAuthorizationURL()));
activity.startActivityForResult(intent, TWITTER_REQUEST_CODE);
Manifest
<activity android:name=".TwitterLinkActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data
android:scheme="http"
android:host="test.com" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Twitter Developer App Settings
Clicking twitter button on my app, Web Browser (chrome android) is opened.
And I log in twitter account and click "accept app" button ("애플리케이션 승인" in below image, UZTest is my test twitter app name.)
I am not native English speaker. So I do not know exactly words in English...
I think browser link to http://test.com/callback?~~~~. And My app catch this url, and start activity.
But my app can not... It just link http://www.test.com in chrome android browser.
I tried change callback url = "myapp://test.com", but only http(or https) is only available. (Twitter Developer)
How can I receive oauth token?
I did sovle it!
Below two value is not same value (?)
final String TW_CALLBACK_URL_STRING = "http://test.com/callback";
Callback URL: http://test.com/callback (OAuth Setting in Twitter Developer)
1 is only use my app. So I change to "myscheme://myhost" in java code and manifest file.
2 is not oauth request callback url (I do not know exactly what.)
Then It works fine.