Maximilian Kindshofer
Maximilian Kindshofer

Reputation: 2843

Getting a request token from Django OauthToolkit via React-Native

I am trying to optain a token from Django - OauthToolkit but I only get the "unsupported_grant_type" error:

Here is what I have writen in react-native:

async getToken (client_id, client_key, username, password) {
     let response = await fetch('https://example.com/o/token/', {
         method: 'POST',
         headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
         body: JSON.stringify({
           'client_id': client_id,
           'client_secret': client_key,
           'grant_type': 'password',
           'username': username,
           'password': password,
         })
       })
       let responseJson = await response.json()
       var token = responseJson.error <- written to see the error (shoul be responseJson.acces_token)
       this.setState({token})
}

other posts mentioned it could be an error in the headers - but it leaves me clueless right now.

Upvotes: 3

Views: 655

Answers (1)

ChampR
ChampR

Reputation: 782

After scratching my head and countless google searches, here's how I did it.

allow me to make some assuptions

  1. Assume your backend server works fine, and any endpoints are protected.
  2. Assume when you go to access an endpoint you get the error

    "detail": "Authentication credentials were not provided."

  3. Assume you can authenticate/get access token from postman or by sending a POST request to /o/token with the parameters

    • username
    • password
    • client_id
    • grant_type

With django-oauth-toolkit, it's crucial to send the data/body as

'Content-Type': 'application/x-www-form-urlencoded'

Note: My approach might not be neat so I welcome any constructive criticism/advise

import { AUTH_LOGIN} from 'react-admin';
var  _client_id = 'xxxxxxxxx';
var _grant_type = 'password';

export default (type, params) => {
    if (type === AUTH_LOGIN) {
        const {username, password } = params;
        let _data = "grant_type="+_grant_type+"&username="+username+"&password="+password+"&client_id="+_client_id
        const request = new Request('http://localhost:8000/api/ps/o/oauth/token/', {
            method: 'POST',
            headers: new Headers({ 
            'Content-Type': 'application/x-www-form-urlencoded',}),
             body : _data,
        })
        return fetch(request)
            .then(response => {
                if (response.status < 200 || response.status >= 300) {
                    throw new Error(response.statusText);
                }
            return response.json();
        })
        .then(({ access_token }) => {
            localStorage.setItem('token', access_token);
        });
}

return Promise.resolve();

}

Finally yet importantly, /o/token returns a dictionary with key 'access_token' and not token. As such, modify your code as highlighted below

.then(({ access_token }) => {localStorage.setItem('token', access_token);});

Upvotes: 1

Related Questions