oauth-2.0elixirreddithttpoison

Reddit api oauth authentication elixir


I am trying to retrieve the access token. I have managed to make the user authorize my application, now i am trying to retrieve the access token. Here is the reddit oauth2 documentation: https://github.com/reddit-archive/reddit/wiki/oauth2 and here is the HTTPoison post request i am using: https://hexdocs.pm/httpoison/HTTPoison.html#post/4

I have no idea how to make the post request, should the client_id be at the body or at the header etc.

  def get_oauth_token(token, state) do
    # TODO: compare state with old state to prevent malicious users
    cfg = config()

    url = 'https://www.reddit.com/api/v1/access_token'
    body  = %{
      grant_type: "authorization_code",
      code: token,
      redirect_uri: cfg[:redirect_uri],
      client_id: cfg[:client_id],
      client_secret: cfg[:client_secret]
    }
    |> Jason.encode()
    |> ok()

    HTTPoison.post(url, body, [
      {"Accept", "application/json"},
      {"Content-Type", "application/x-www-form-urlencoded"},
    ])
  end

  defp ok({:ok, response}), do: response

I am getting a status code of 401

expected result

{
    "access_token": Your access token,
    "token_type": "bearer",
    "expires_in": Unix Epoch Seconds,
    "scope": A scope string,
    "refresh_token": Your refresh token
}

Solution

  • The API is expecting application/x-www-form-urlencoded, so you shouldn't be encoding into JSON.

    According to the Reddit docs, you also need to encode your client_id and client_secret into the Authorization header using HTTP Basic authentication.

    url = "https://www.reddit.com/api/v1/access_token"
    
    headers = [
      {"Content-Type", "application/x-www-form-urlencoded"},
      {"Authorization", "Basic " <> Base.encode64("#{cfg.client_id}:#{cfg.client_secret}")}
    ]
    
    data = [
      grant_type: "authorization_code",
      code: token,
      redirect_uri: cfg.redirect_uri
    ]
    
    HTTPoison.post(url, {:form, data}, headers)
    

    Check out the documentation of HTTPoison.Request for the {:form, data} syntax for posting forms url-encoded.