Ad

OAuth Invalid_grant Error On Coinbase Using Oauth2_client Flutter Package

- 1 answer

I am using the oauth2_client package for flutter, connecting to the Coinbase API via OAuth 2.0.

From what I can tell, Coinbase uses the code flow for authentication. This is the same as Github. This is important to note because I can successfully auth into Github using the oauth2_client package for flutter.

To connect to Github I used the existing client:

import 'package:oauth2_client/oauth2_client.dart';
import 'package:meta/meta.dart';

/// Implements an OAuth2 client against GitHub
///
/// In order to use this client you need to first create a new OAuth2 App in the GittHub Developer Settings (https://github.com/settings/developers)
///
class GitHubOAuth2Client extends OAuth2Client {
  GitHubOAuth2Client(
      {@required String redirectUri, @required String customUriScheme})
      : super(
            authorizeUrl: 'https://github.com/login/oauth/authorize',
            tokenUrl: 'https://github.com/login/oauth/access_token',
            redirectUri: redirectUri,
            customUriScheme: customUriScheme) {
    accessTokenRequestHeaders = {'Accept': 'application/json'};
  }
}

Then I created a method to call within the app:


void _oauthMethod() async {
    //clientID
    String cID = 'x';

    //clientSecret
    String cSecret = 'y';

    OAuth2Client client = GitHubOAuth2Client(
        redirectUri: 'my.app://oauth2redirect', customUriScheme: 'my.app');

    AccessTokenResponse tknResp = await client.getTokenWithAuthCodeFlow(
        clientId: cID, clientSecret: cSecret, scopes: ['repo']);

    http.Response resp = await http.get('https://api.github.com/user/repos',
        headers: {'Authorization': 'Bearer ' + tknResp.accessToken});
   
  }

Calling this function brings up the OAuth page for Github, I can sign in, and if I print resp it shows a list of my repos. As expected.

Using the same method for Coinbase, I first create the new class:

class MyOAuth2Client extends OAuth2Client {
  MyOAuth2Client(
      {@required String redirectUri, @required String customUriScheme})
      : super(
            authorizeUrl:
                'https://www.coinbase.com/oauth/authorize', //Your service's authorization url
            tokenUrl:
                'https://api.coinbase.com/oauth/token', //Your service access token url
            redirectUri: redirectUri,
            customUriScheme: customUriScheme) {
    this.accessTokenRequestHeaders = {'Accept': 'application/json'};
  }
}

Then I create the method to call:

void _coinbaseAuth() async {
    String cID = 'x';
    String cSecret = 'y';
    MyOAuth2Client client = MyOAuth2Client(
        redirectUri: 'my.app://oauth2redirect', customUriScheme: 'my.app');

    AccessTokenResponse tknResp = await client.getTokenWithAuthCodeFlow(
        clientId: cID, clientSecret: cSecret, scopes: ['wallet:user:read']);

    print(tknResp);


    //code fails 
    //http.Response resp =
    //        await http.get('https://api.coinbase.com/v2/user', headers: {
    //      'Authorization': 'Bearer ' + tknResp.accessToken,
    //      'Content-Type': 'application/json',
    //      'Charset': 'utf-8'
    //    });


  }

I can't run the http.Response part, because it is filled with nulls. The tknResp prints:

HTTP 401 - invalid_grant The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.

I have tried creating a new OAuth application in Coinbase, however this doesn't work.

Does anyone know why I'm getting this error? It's confusing for me as the code worked with Github using the exact same OAuth flow.

Ad

Answer

I tested the auth flow manually using postman, which enabled me to get the token.

After some testing, I was able to get the token with the dart package by adding the extra auth code params & disabling PKCE

    AccessTokenResponse tknResp = await client.getTokenWithAuthCodeFlow(
        clientId: cID,
        clientSecret: cSecret,
        scopes: ["wallet:user:read"],
        authCodeParams: {
          "grant_type": "authorization_code",
          "redirect_uri": "my.app://oauth2redirect"
        },
        enablePKCE: false,
        state: 'OYWjs_95M6jlkvy5');
Ad
source: stackoverflow.com
Ad