OAuth authentication (without mobile phone interaction)

Hello,

I'd like to implement an application that uses a different way of OAuth authentication compared to the examples in the SDK (makeOAuthRequest).
Instead of asking the user for username/password in the browser, they have to be provided already as parameters in the request.
Unfortunately I couldn't get it to work neither with makeOAuthRequest, nor with makeWebRequest. Maybe one of you already run into a similar problem and can assist here.

There's working example code (written in Python) for the usecase here: https://github.com/ChristianKuehnel/...init__.py#L70:

url = 'customer.bmwgroup.com/.../authenticate'
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
params = {
'username': self._username,
'password': self._password,
'client_id': self._clientid,
'redirect_uri': 'www.bmw-connecteddrive.com/.../external-dispatch.html',
'response_type': 'token',
'scope': 'authenticate_user fupo',
'state': self._random_string(79),
}
response = requests.post(url, data=urlencode(params), headers=headers, allow_redirects=False)
if response.status_code != 302:
raise IOError('Unknown status code {}'.format(response.status_code))

url_with_token = urllib.parse.parse_qs(response.headers['Location'])
self._oauth_token = url_with_token['access_token'][0]


Here's my attempt with makeOAuthRequest:

var url = "customer.bmwgroup.com/.../authenticate";
var params = {
"username" => "xxx",
"password" => "yyy",
"client_id" => client_id,
"redirect_uri" => "www.bmw-connecteddrive.com/.../external-dispatch.html",
"response_type" => "token",
"scope" => "authenticate_user fupo",
"state" => state
};

Communications.makeOAuthRequest(
url,
params,
"www.bmw-connecteddrive.com/.../external-dispatch.html",
Communications.OAUTH_RESULT_TYPE_URL,
{"access_token" => "token"}
);


This opens an 'empty' browser window (405 status code) because it does a GET instead of the expected POST.
The OAuthCallback is not called.

Then I tried to use a simple makeWebRequest instead (which would probably be preferable as there's no user input required on the mobile phone side):

var url = "customer.bmwgroup.com/.../authenticate";
var params = {
"username" => "xxx",
"password" => "yyy",
"client_id" => client_id,
"redirect_uri" => "www.bmw-connecteddrive.com/.../external-dispatch.html",
"response_type" => "token",
"scope" => "authenticate_user fupo",
"state" => state
};
var options = {
:method => Communications.HTTP_REQUEST_METHOD_POST,
:headers => {
"Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED,
},
:responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_URL_ENCODED
};
Communications.makeWebRequest(url, params, options, method(:onOAuthResponse));


Here I always get the callback called with error 400.
I've changed the URL to a local webserver that would just print the received headers to compare it with the request of the Python script to make sure that everything is sent correctly. The problem here might be that the server doesn't reply with 200, but with 302 and maybe this redirect is not handled correctly (there's a allow_redirects=False necessary in Python). Even if it would work, I'm wondering if it would be possible to extract the token because that would be sent as parameter of the 'Location' header in the response.

Is it possible to make this kind of OAuth request from the watch only? Once I've manually added the access_token in my calls to request the data, everything works flawlessly. Therefore it would be really unfortunate if a companion app would be required just to proxy the token request.

If the necessary bits are not yet available, maybe Garmin could extend their APIs to allow this.
  • Former Member
    Former Member over 7 years ago
    I'd like to implement an application that uses a different way of OAuth authentication compared to the examples in the SDK (makeOAuthRequest).
    Instead of asking the user for username/password in the browser, they have to be provided already as parameters in the request.

    I know this response won't be what you are looking for, but why do you want this? It still requires the phone interaction initially for the user to set their username and password. It also requires users who have trust in your apps ability to keep their account information secure, ignoring the fact that account information would be stored as plaintext in the initial request. Is it a breaking mode of use for the users to enter their information through the browser?
  • I know this response won't be what you are looking for, but why do you want this? It still requires the phone interaction initially for the user to set their username and password. It also requires users who have trust in your apps ability to keep their account information secure, ignoring the fact that account information would be stored as plaintext in the initial request. Is it a breaking mode of use for the users to enter their information through the browser?


    I would prefer the 'normal' OAuth flow as well and not deal with the credentials at all, but the service simply doesn't support it.
  • Former Member
    Former Member over 7 years ago
    Ah, that is unfortunate. I might guess the issue to be that the response is sent in a redirect, but I wouldn't know how those are handled internally and someone else should chime in with better info. In the mean time you could try playing around with allowing redirects in python to see if you can manage to get it working that way. I believe in the past some people have wrapped their own services around such APIs, but that of course requires you to host and manage the service somewhere. You could also consider writing a partner mobile application (Android, iOS) that would handle the requests for you, but that would require the user to execute two installs.