Nokia-Withings Oauth2 Get Authentification Code - withings

I do struggle to get the Nokia-Withings OAuth2 flow working with a flask app running on the localhost. I have made sure that in the /etc/hosts I have a redirect from callback url (nokia.velometria.com) to the 127.0.0.1 to make sure that all callback requests are going back to the app.
What is happening is that the original get request to the nokia authorize2 is automatically redirected to the account_login and never returns a request with a code to the specified callback url (nokia.velometria.com/code.
Here is a flask code I use:
from flask import Flask, request
import requests
import os
app = Flask(__name__)
#app.route("/code", methods=["GET"])
def nokia_code():
"""I expect the url with a code to be sent here"""
return request.get_data()
#app.route("/", methods=["GET", "POST"])
def nokia_callback():
"""OAuth 2.0 - Get your authentication code"""
if request.method == "POST": # just for debugging
app.logger.info("POST request data: {}".format(request.get_data()))
app.logger.info("POST request path: {}".format(request.path))
return "post"
else: # the actual GET request
url = "https://account.health.nokia.com/oauth2_user/authorize2"
client_id = os.getenv("NOKIA_CLIENT_ID", None)
params = {
"response_type": "code",
"client_id": client_id,
"state": "/",
"scope": "user.info",
"redirect_url": "http://nokia.velometria.com/code"
}
r = requests.get(url, params=params)
app.logger.info("url: {}".format(r.url))
app.logger.info("headers: {}".format(r.headers))
app.logger.info("history: {}".format(r.history))
return r.text
if __name__ == "__main__":
app.run(debug=True)
And here is a flask log I've got in return:
[2018-08-05 22:24:28,136] INFO in nokia_callback: url: https://account.health.nokia.com/oauth2_user/account_login?response_type=code&client_id=***&state=%2F&scope=user.info&redirect_url=http%3A%2F%2Fnokia.velometria.com%2Fcode&b=authorize2
[2018-08-05 22:24:28,136] INFO in nokia_callback: headers: {'Date': 'Sun, 05 Aug 2018 20:24:25 GMT', 'Server': 'Apache', 'Content-Security-Policy': "frame-ancestors 'self' https://dashboard.health.nokia.com/", 'Strict-Transport-Security': 'max-age=2592000', 'X-XSS-Protection': '1', 'X-Content-Type-Options': 'nosniff', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'Vary': 'Accept-Encoding', 'Content-Encoding': 'gzip', 'X-Frame-Options': 'ALLOW-FROM https://dashboard.health.nokia.com/', 'Content-Length': '2373', 'Content-Type': 'text/html;charset=UTF-8'}
[2018-08-05 22:24:28,136] INFO in nokia_callback: history: []
127.0.0.1 - - [05/Aug/2018 22:24:28] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2018 22:24:28] "GET /min/g=baseCSS,blockv4CSS&2ef1f384 HTTP/1.1" 404 -
127.0.0.1 - - [05/Aug/2018 22:24:28] "GET /min/g=basev4JS&2ef1f384 HTTP/1.1" 404 -
127.0.0.1 - - [05/Aug/2018 22:24:28] "GET /min/g=basev4JS&2ef1f384 HTTP/1.1" 404 -
[2018-08-05 22:24:33,318] INFO in nokia_callback: POST request data: b'email=&password=&is_admin=f&csrf_token=***'
[2018-08-05 22:24:33,318] INFO in nokia_callback: POST request path: /
127.0.0.1 - - [05/Aug/2018 22:24:33] "POST / HTTP/1.1" 200 -
Note that the requests url is authomatically redirected to account_login from authorize2 and than calls a POST at the flask server with account credentials - definetely not a behaviour I was expectiong.
Any thoughts on how to get it working?

I had an similar issue. Basically the https://account.withings.com/oauth2_user/authorize2 url should be opened in the browser window by the user. (So you could open it maybe in another popup window or iframe.) The site will ask for application permissions and asks the user to login if needed.
After the user has clicked that your application has permission to use his data, the site will redirect to your uri callback with parameters.
So your http://nokia.velometria.com/ should be listening for request parameters given by the API.

Related

Axios network error (Invalid imageTag) when querying a Flask resource from React Native iOS app

I have a Flask app set up with a few endpoints. These endpoints work fine when accessed from postman or a browser.
I also have a React Native app set up (using an Expo template), in which I try to query this resource from iOS:
const testApiCall = async (): Promise<string> => {
try {
const url = `${baseUrl}/users`;
const response = await axios.get(url);
console.log(response.data);
return response.data.toString();
} catch (error) {
console.log(error.request)
console.log(" a " + error.request?._response);
console.log(error);
}
}
baseUrl is the full IP, not just localhost.
The /users endpoint returns json of the app's users. However, when calling this, I get the following output:
a Invalid imageTag: 192.168.1.191:80/users
[AxiosError: Network Error]
(excluding the error.request since it's long and probably doesn't provide any additional context - will edit this post if it would be useful!)
I can't find any reason for the "invalid imageTag" error. Intermittently, the flask app will get logs including a 404 request for the favicon:
[06/May/2022 21:55:05] "GET /users HTTP/1.1" 200 -
[06/May/2022 21:55:05] "GET /favicon.ico HTTP/1.1" 404 -
[06/May/2022 21:56:15] "GET /users HTTP/1.1" 200 -
[06/May/2022 21:56:16] "GET /favicon.ico HTTP/1.1" 404 -
I even tried to make an endpoint in the flask app to return a generic .ico file when requesting /favicon.ico but behavior didn't change. Now, I stopped getting any kind of request on my flask app when using my React Native app. I still get logs when accessing the endpoints from postman, though.
I also used flask_cors:
CORS(app, resources={r'/*': {'origins': '*'}})
This one has been a real head-scratcher for me and I'm having trouble finding any similar issues, so I'd really appreciate any help! Happy to provide additional context that could be useful, too.
A request to https://jsonplaceholder.typicode.com/todos/1 worked without an issue. Tried with http:// and that worked too.
Added this to app.json but it didn't help:
"ios": {
"supportsTablet": true,
"infoPlist": {
"NSAppTransportSecurity" : {
"NSAllowsArbitraryLoads" : true,
"NSAllowsLocalNetworking": true
}
}
},
Turns out my logic for getting the baseUrl excluded the http://. Prepending the baseUrl with 'http://' solved the issue. It's always something obvious that I miss!

Pyshark does not show \r\n\r\n in the HTTP header and instead shows \r\n

I am using pyshark to parse .pcap files specifically with HTTP packets. Unlike as in Wireshark, where it shows the \r\n\r\n bytes at the end of the HTTP header, pyshark does not show them and instead shows a single \r\n.
Is there any way to properly parse the HTTP layer of the packet to display the \r\n\r\n's?
If so, how? I have done a fair amount of searching through the web but the sources are limited and does not answer my question.
Also, with pyshark, the headers do not come in the same order as seen on Wireshark. Is there any reason to that as well?
Python code
#!/bin/env python3
import pyshark
packets = []
with pyshark.FileCapture('testing-mutillidae1.pcap') as capture:
for pkt in capture: # storing packets in list
packets.append(pkt)
print(packets[3]) # printing packet details of packet no. 4
HTTP header
I have included the full output of the packet on pastebin: https://pastebin.com/qxjxY6Hw . Since it is too long, I have added only the HTTP layer in this question
Layer HTTP:
GET /mutillidae/index.php?page=add-to-your-blog.php HTTP/1.1\r\n
Expert Info (Chat/Sequence): GET /mutillidae/index.php?page=add-to-your-blog.php HTTP/1.1\r\n
GET /mutillidae/index.php?page=add-to-your-blog.php HTTP/1.1\r\n
Severity level: Chat
Group: Sequence
Request Method: GET
Request URI: /mutillidae/index.php?page=add-to-your-blog.php
Request URI Path: /mutillidae/index.php
Request URI Query: page=add-to-your-blog.php
Request URI Query Parameter: page=add-to-your-blog.php
Request Version: HTTP/1.1
Host: 10.0.2.13\r\n
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: en-US,en;q=0.5\r\n
Accept-Encoding: gzip, deflate\r\n
Referer: http://10.0.2.13/mutillidae/index.php\r\n
Connection: keep-alive\r\n
Cookie: showhints=0; PHPSESSID=511be46cfd6922ff8sqqhtqmbn\r\n
Cookie pair: showhints=0
Cache-Control: max-age=0\r\n
Full request URI: http://10.0.2.13/mutillidae/index.php?page=add-to-your-blog.php
HTTP request 1/1
\r\n
Upgrade-Insecure-Requests: 1\r\n
Cookie pair: PHPSESSID=511be46cfd6922ff8sqqhtqmbn
Here is the screenshot on my wireshark (I cannot post pictures yet)

Oauth2 token request does not contain redirect_uri

I'm trying to setup an Oauth2 Authoization Code flow with Bitbucket Oauth in micronaut.
I've setup both Github and Bitbucket in my Mirconaut config for auth.
Whenever I (try to) login with Bitbucket, I get an redirect_uri does not match error.
{"message":"Internal Server Error: error: invalid_request, errorDescription: redirect_uri does not match, errorUri: null"}
After doing some research and enabling some trace logging I see that redirect_uri is missing in the access token request.
09:33:53.263 [nioEventLoopGroup-1-5] DEBUG i.m.http.client.DefaultHttpClient - Sending HTTP Request: POST /site/oauth2/access_token
09:33:53.263 [nioEventLoopGroup-1-5] DEBUG i.m.http.client.DefaultHttpClient - Chosen Server: bitbucket.org(-1)
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - Accept: application/json
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - Authorization: Basic xxxxxxx
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - content-type: application/x-www-form-urlencoded
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - host: bitbucket.org
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - connection: close
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - content-length: 53
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - Request Body
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - ----
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - code=PuaUDFGTmQ4Gh9gJPM&grant_type=authorization_code
09:33:53.264 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - ----
09:33:53.762 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - HTTP Client Response Received for Request: POST https://bitbucket.org/site/oauth2/access_token
09:33:53.762 [nioEventLoopGroup-1-5] TRACE i.m.http.client.DefaultHttpClient - Status Code: 400 Bad Request
Whenever I recreate the call with something like curl and add the (default) redirect_uri, I get back a proper access token and am able to use this.
Is there any way to add the redirect_uri to the token request? Is this a bug? As far as I know, the redirect_uri is required in the token request, if it was also present in the previous authorization request (see https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3)
Thanks,
Danny
I had this issue when setting up OAuth2 on Bitbucket using Tornado. I hope it helps you track down this issue specifically in micronaut
As you know, there are two stages to the authentication.
Authorize (https://bitbucket.org/site/oauth2/authorize) which returns a token and
Authorization code grant (https://bitbucket.org/site/oauth2/access_token)
They both take a redirect_uri in the POST body but they have to be identical for both calls. As long as they start with the same uri that is specified in the OAuth consumer settings in Bitbucket (e.g https://f.q.d.n/), they can point to a more specific path (e.g https://f.q.d.n/some/specific/end-point)
Importantly, they must be the same for both calls or you will be the redirect_uri does not match error.

DART HttpRequest does not provide authorization header for CORS OPTIONS request

I try to do a POST request with HttpRequest (dart:html) to call a rest service secured with basic authentication.
HttpRequest request = new HttpRequest(); // create a new XHR
var url = "http://localhost:8082/xyz";
request.open("POST", url, async: false); // POST the data to the server
String username = "foo";
String password = "bar";
final auth = CryptoUtils.bytesToBase64(UTF8.encode("$username:$password"));
request.setRequestHeader('authorization',"Basic $auth");
request.setRequestHeader('content-type',"application/json");
request.setRequestHeader("accept", "application/json");
String jsonData = '{"language":"dart"}'; // etc...
request.send(jsonData); //exception 401 Unauthorized
Before performing the POST call the OPTIONS call is performed (issued by dart:html) without the authorization header. This leads into an 401 Unauthorized response.
Request header:
Accept:*/*
Accept-Encoding:
gzip,deflate,sdch
Accept-Language:
en-US,en;q=0.8
Access-Control-Request-Headers:
authorization, content-type, accept
Access-Control-Request-Method:
POST
Cache-Control:
max-age=0
Connection:
keep-alive
Host:
localhost:8082
Origin:
http://localhost:63342
Referer:
http://localhost:63342/dart_client/test/all_test.html
User-Agent:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.0 (Dart) Safari/537.36
Reponse header:
Content-Length:
0
Date:
Mon, 02 Feb 2015 23:33:58 GMT
Server:
Jetty(9.2.7.v20150116)
WWW-Authenticate:
basic realm="xyzrealm"
Is there a way to provide the authorization header to the OPTIONS call?
Any suggestions would be great. Thanks
The OPTIONS request is made by the browser automatically and you can't modify that request. The server needs to allow the OPTIONS preflight request without authentication.
See http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
The user credentials are excluded.

401 - Token invalid when requesting video feed

I'm at a loss for what's wrong. I'm always getting com.google.gdata.client.GoogleService$SessionExpiredException: Token invalid Token invalid when making API requests.
I have the following flow:
link user account
use credentials to get video upload entries
The code I use to link the user (get permission for my application) uses the JdoDataStoreFactory to persist user tokens and refresh info between API calls.
I used the following scopes when I ask the user to authorize my apps:
https://www.googleapis.com/auth/youtube.upload
https://www.googleapis.com/auth/youtube.readonly
Using GoogleAuthorizationCodeFlow I do a loadCredentials passing in the userId from my application that I used when requesting their auth token. I then feed those credentials to YouTubeService's getFeed method, requesting the url for video feeds: http://gdata.youtube.com/feeds/api/users/default/uploads
It looks like this:
service.setOAuth2Credentials(credentials)
videoFeed = service.getFeed(new URL(USER_FEED_PREFIX + DEFAULT_USER
+ UPLOADS_FEED_SUFFIX), VideoFeed.class)
After this executes, I always get the stacktrace:
com.google.gdata.client.GoogleService$SessionExpiredException: Token
invalid Token invalid Token invalid Error
401
at
com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:570)
at
com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:560)
at
com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:538)
at
com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:536)
at com.google.gdata.client.Service.getFeed(Service.java:1135) at
com.google.gdata.client.Service.getFeed(Service.java:998) at
com.google.gdata.client.GoogleService.getFeed(GoogleService.java:645)
at com.google.gdata.client.Service.getFeed(Service.java:1017)
The way I'm initiating my request to my service is via curl, my command looks like this:
curl http://localhost:8080/user/someUserId/content
Using Wireshark I see the following in my request:
GET /feeds/api/users/default/uploads HTTP/1.1
Authorization: Bearer <the_auth_token_for_the_user>
User-Agent: MyApp YouTube-Java/1.0 GData-Java/null(gzip)
X-GData-Client: MyApp
Accept-Encoding: gzip
GData-Version: 2.0
Cache-Control: no-cache
Pragma: no-cache
Host: gdata.youtube.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
I'm stuck.
Ok, I figured this out. I was trying to query the user's uploaded videos, and apparently for an app to do that it has to be authorized for the https://www.googleapis.com/auth/youtube scope, not the scopes I had configured

Resources