skip to Main Content

I’m making a flutter app using Spotify’s API. I have a basic homepage that uses a button to launch a browser to login to Spotify. Here is my backend code:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:uni_links/uni_links.dart';

class SpotifyAuth with ChangeNotifier {
  final String CLIENT_ID = "My client ID";
  final String ClIENT_SECRET = "My client secret";
  final String REDIRECT_URI = "http://localhost:8000/callback";
  final String SCOPE = 'user-read-private user-read-email';
  // var state = 'your-state';
  late String _accessToken;
  late String _refreshToken;

  Uri createAuthenticationUri(){
    var query = [
      'response_type=code',
      'client_id=$CLIENT_ID',
      'scope=${Uri.encodeComponent(SCOPE)}',
      'redirect_uri=${Uri.encodeComponent(REDIRECT_URI)}',
    ];

    var queryString = query.join('&');
    var url = 'https://accounts.spotify.com/authorize?' + queryString;
    var parsedUrl = Uri.parse(url);
    return parsedUrl;
  }

  Future<void> launchInBrowser() async {
    if (!await launchUrl(
      createAuthenticationUri(),
      mode: LaunchMode.externalApplication,
    )){
      throw Exception('Could not launch Url');
    }
  }

  Future<void> launchAuth() async {
    await launchInBrowser();
    await initUniLinks();
  }

  Future<void> getAccessToken(String code) async {
    var body = {
      "grant_type": "authorization_code",
      "code": code,
      "redirect_uri": REDIRECT_URI,
      "client_id": CLIENT_ID,
      "client_secret": ClIENT_SECRET
    };
    // Create a request header with the required information
    var header = {
      "Content-Type": "application/x-www-form-urlencoded",
      "Authorization":
          "Basic ${base64Encode(utf8.encode("$CLIENT_ID:$ClIENT_SECRET>"))}"
    };
    // Send the request to the Spotify token endpoint
    var response = await http.post(
        Uri.parse("https://accounts.spotify.com/api/token"),
        body: body,
        headers: header);

    // Check if the request was successful
    if (response.statusCode == 200) {
      // Parse the JSON response
      var data = json.decode(response.body);
      // Get the access token from the response
      String accessToken = data["access_token"];

      // Store the access token for future use
      // ...
      _accessToken = accessToken;
    } else {
      print("Error");
    }
  }

  Future<void> initUniLinks() async {
    // Get the latest initial link
    String? initialLink = await getInitialLink();

    // Check if the link contains a Spotify authorization code
    if (initialLink != null && initialLink.contains("code=")) {
      // Extract the code from the link
      String code = initialLink.split("code=")[1];

      // Use the code to get an access token from Spotify
      getAccessToken(code);
    }
    else{
      print("Nothing");
    }
  }
}

My redirect URI is set in the spotify dashboard.

My app widget calls luanchAuth();
and then it should wait for the authentication code with initUniLinks() but it seems like initUniLinks() executes immediately without waiting for the authentication. When I authenticate in Spotify, it throws a generic "can’t connect to localhost" error page but the url includes the auth code that I need.

Not sure what I’m doing wrong here. Admittedly I’m new to Oauth and app-api-connections in general but I thought this would work.

2

Answers


  1. REDIRECT URI is the problem here, You cannot have redirect URI with localhost it fails. either use ngrok and provide the mapped https url or host your callback url and provide it.

    Login or Signup to reply.
  2. Use the custom scheme for redirect_uri, something like this my-app://token/callback. See App Settings for Spotify rules.

    Then configure the application for Deep Linking to receive the authentication response.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search