nightscout / minimed-connect-to-nightscout

Community edition of original
MIT License
47 stars 138 forks source link

CareLink Recaptcha EU #47

Open m0rt4l1n opened 1 year ago

m0rt4l1n commented 1 year ago

Minimed seems to have implemented recaptcha with the standard https://carelink.minimed.eu/patient/sso/login authorization, at least in Europe, thus it does not work for me anymore...

m0rt4l1n commented 1 year ago

For reference, this it what the login ui looks like

image
stijnbrouwers commented 1 year ago

+1 Same here. Unable to log in due to the recaptcha

m0rt4l1n commented 1 year ago

There seems to be an refresh token endpoint in the sso configs (https://carelink.minimed.eu/configs/v1/sso_cp_eu_v4.json), so maybe an manual login with recaptcha and automated refresh would be possible...

stijnbrouwers commented 1 year ago

Technically, I suppose it would be possible. However, that's a workaround that requires some recoding. I think a more sustainable solution would be to analyse the traffic generated by the official apps to see how these services resolve it and implement that it here... My best bet would be that there is a different URL to login for retrieving the authentication token, or some kind of parameter we need to use with the current URL.

m0rt4l1n commented 1 year ago

In the App I also had to use recaptcha so this seems to be the only option...

stijnbrouwers commented 1 year ago

Ah seriously? I don’t remember seeing it.

If the app solves it like that I think you are right, we might be required to provide an initial token and use the refresh url afterwards…

seanch80 commented 1 year ago

Medtronic really doesn't like 3rd-party clients it seems... It could also be that some clients are abusing the servers by polling too frequently. I only poll data every 5 or 6 minutes myself, as sensor data is only updated every 5 minutes anyway. There could be a small delay (latency) by doing this obviously, but if we really want Medtronic to not be so aggressive in trying to block 3rd-party clients, polling less often might be preferred. By analyzing the timestamps of new sensor data the polling could be synchronized so it always tries to poll 10-20 seconds after it expects new sensor data to be there, but in any case never more frequently than every 5 minute.

Lintzman commented 1 year ago

I also am unable to login after the Recaptcha was added to the login screen. Anyway to get around this?

bewest commented 1 year ago

Howdy all, thanks for everyone's interest in this project! I have rewritten much of this library in the form of nightscout-connect's minimedcarelink driver. The reason for the new plugin was to condense the number of (deprecated) http library plugins, Nightscout specific integration code, and ability to modify driver features and add vendors without modifying Nightscout into a single node package.

Common driver features usually involve scheduling updates, handling error and retry logic. I experimented using xstate to describe a series of state machines and inject vendor specific behavior into the actions and services the machine makes available. This helps standardize scheduling and retry concerns. In fact, the new driver consistently schedules updates to occur such that it rarely misses an update by more than a minute. It turns out Medtronic updates at the very end of the cycle, so additional time has been tuned in addition to randomized jitter to help avoid any kind of thundering herd problems we've had in the past.

Session Refresh

I like this idea but had a lot of trouble implementing this before recaptcha was introduced. In fact I've been trying to make this work consistently for weeks now and have not been able to do so, although I'm sure it's my fault. More work/contributions needed.

Recaptcha

Some brief looking around indicates that the way to do this is download the sound file, which can then be decoded and entered. The xstate and Nightscout integration in the new plugin opens the possibility of communicating messages from the NS UI back and forth to the plugin. It's foreseeable that we could develop features that enable the Nightscout operator to navigate through the obstacle. Many projects on github use AI image or sound recognition, but we can also assume there is a Nightscout operator for setup purposes. Unclear how long a refreshed session will last.

sbc2280 commented 1 year ago

Please see a couple of samples..

https://github.com/nightscout/nightscout-connect/commit/56383804f7132eb9d51ac7ecd761ab2802594881

https://github.com/anguriskit24/CareLinkJavaClient/blob/22defbd961a5092c7ed40f3f64adc0170928df39/src/main/java/info/nightscout/medtronic/carelink/client/CareLinkClient.java#L308-L310

sbc2280 commented 1 year ago

s now and have not been able to do so, although I'm sure it's my fault. More work/contributions needed.

it looks like there is a cookie that shows how long session/cookie lasts and as long as it gets refreshed before it expires seems to work.

seanch80 commented 1 year ago

Is anyone using the Guardian Monitor app? I hear people in my country are using this app still, and I don't see any new versions released for either Apple or Android recently. Maybe this app is using a different protocol?

ex33xv commented 1 year ago

Is anyone using the Guardian Monitor app? I hear people in my country are using this app still, and I don't see any new versions released for either Apple or Android recently. Maybe this app is using a different protocol?

Update: unfortunately , it's just a shell w/ some UI improvement to Carelink, still automatically logging off due to inactivity.

@seanch80 I'm testing GuardianMonitor 1.0 now, it require id/pwd & manually reCAPTCHA identification to login, so far it successfully maintains the session without automatically logging off due to inactivity.

stijnbrouwers commented 1 year ago

So I did a dirty little POC but I got it working by prefetching the token. ( See: https://github.com/stijnbrouwers/minimed-connect-to-nightscout/commit/38d02a8fdc14c16699f7e98b89697374330ce7e2 )

FYI, this is not a sustainable solution but rather proves the issue can be solved by prefetching the token and use the tokenrefresh from that point onward. This solution is based upon the work proposed by @sbc2280 ...

How to use it

What you need to do is open up a browser and navigate to carelink.minimed.eu (for EU residents). When you see the regular login page, open your browser's "Developer Tools" image Now login with your username, password and pass the "reCaptcha".

After login in, you can search for the entry with file = "/" in the Developer Tool's "Network"-tab image Under cookies, copy the values for both:

Pass these values to the application as environment variables with the same name and casing as the cookies (auth_tmp_token & c_token_valid_to).

How it works

The first time entering the checkLogin function "FIRST_TIME_LOGIN"-variable will be set to true.

Whenever FIRST_TIME_LOGIN = true, the new environment variables we just created will be read as if they were cookies and used to do a token refresh.

When a succesfull login has been done, the FIRST_TIME_LOGIN-variable will be set to false and from then on, the process should be the same as before...

bewest commented 1 year ago

Excellent work! If possible, I'd like to move this conversation to nightscout-connect. https://github.com/nightscout/nightscout-connect/issues/25

Were you able to observe any kind of average session duration, or is it very dynamic? The nightscout-connect code is built with the (erroneous?) assumption that sessions will expire at a predictable rate and will attempt to renew the session before that occurs, independently of anything, including what the client says. This could be refactored to depend on what the server claims instead.

stijnbrouwers commented 1 year ago

@bewest I'm OK with moving the discussion.

No, I am not aware of the average session duration. I see that "minimed-connect-to-nightscout" actually takes the response from the server into account:

if(expire < new Date(Date.now() + 6 * 60 * 1000)) { 
...
}

This line is also the reason why we needed to add 2 cookies, more specifically the "c_token_valid_to"-cookie is involved in this.

I suppose this would be a more solid solution than to presume a certain expiration rate. Especially when manually setting the token since there might be a delay between login in and starting the application like we do in this solution.

bewest commented 1 year ago

I think that is next step in the development: https://github.com/nightscout/nightscout-connect/pull/22

ex33xv commented 1 year ago

Pass these values to the application as environment variables with the same name and casing as the cookies

@stijnbrouwers Is the term "application" in this context referring to "minimed-connect-to-nightscout"? Since reCAPTCHA is blocking access to data from CareLink, which primarily impacts "minimed-connect-to-nightscout" and not "cgm-remote-monitor," correct? Is it feasible to execute this process semi-automatically, meaning manually engaging with reCAPTCHA to acquire the auth_tmp_token and c_token_valid_to, and then adding them to the HTTP object of "minimed-connect-to-nightscout" so that "minimed-connect-to-nightscout" can subsequently transmit data to "cgm-remote-monitor"?

stijnbrouwers commented 1 year ago

@ex33xv Yes, with application I am referring to "minimed-connect-to-nightscout", not the "cgm-remote-monitor".

I am not sure if it's possible with a semi-automatic approach. Typically in an OIDC workflow you provide a redirecturl during the login process, but that needs to be registered on the OIDC server (in this case by Medtronic). So I doubt if it's possible, but to be sure the traffic from the official app should be monitored to see how it works.

The semi-automatic way would also not work for me since I am running the application on a server (without UI) so opening the browser to pass the captcha would not be possible in such a case.

olsky commented 1 year ago

+1 same here, also from dev branch (use of CARELINK_PATIENT), here is the log:


> minimed-connect-to-nightscout@1.5.6 start
> node run.js

[MMConnect] Wait 0 seconds before start
2023-10-05T13:31:55.745Z [Arguments] { '0': 'Logging in to CareLink' }
2023-10-05T13:31:55.748Z [Arguments] { '0': 'EU login 1' }
2023-10-05T13:31:55.752Z [Arguments] {
  '0': 'EU login 1',
  '1': 'https://carelink.minimed.com/patient/sso/login?country=de&lang=en'
}
2023-10-05T13:31:56.451Z [Arguments] {
  '0': 'EU login 2 (url: https://carelink.minimed.eu/patient/sso/login?country=de&lang=en)'
}
2023-10-05T13:31:56.686Z [Arguments] {
  '0': 'EU login 3 (url: https://mdtlogin-ocl.medtronic.com/mmcl/auth/oauth/v2/authorize?locale=null&countrycode=null)'
}
Error: Request failed with status code 400
stack: Error: Request failed with status code 400
    at createError (/home/ubuntu/mmconnect/minimed-connect-to-nightscout/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/home/ubuntu/mmconnect/minimed-connect-to-nightscout/node_modules/axios/lib/core/settle.js:17:12)
    at /home/ubuntu/mmconnect/minimed-connect-to-nightscout/node_modules/axios-cookiejar-support/lib/interceptors/response.js:79:25
    at new Promise (<anonymous>)
    at responseInterceptor (/home/ubuntu/mmconnect/minimed-connect-to-nightscout/node_modules/axios-cookiejar-support/lib/interceptors/response.js:78:9)
    at /home/ubuntu/mmconnect/minimed-connect-to-nightscout/node_modules/axios-cookiejar-support/lib/index.js:130:67
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async doLoginEu3 (/home/ubuntu/mmconnect/minimed-connect-to-nightscout/carelink.js:170:20)
    at async checkLogin (/home/ubuntu/mmconnect/minimed-connect-to-nightscout/carelink.js:284:28)
    at async Object.fetch (/home/ubuntu/mmconnect/minimed-connect-to-nightscout/carelink.js:313:21)
ex33xv commented 1 year ago

Mechanical Turk (mTurk) may be the only solution? ( or 2Captcha, Anti-Captcha, Solve Recaptcha ... might be a better way?)

fjpezuela commented 1 year ago

So I did a dirty little POC but I got it working by prefetching the token. ( See: stijnbrouwers@38d02a8 )

FYI, this is not a sustainable solution but rather proves the issue can be solved by prefetching the token and use the tokenrefresh from that point onward. This solution is based upon the work proposed by @sbc2280 ...

How to use it

What you need to do is open up a browser and navigate to carelink.minimed.eu (for EU residents). When you see the regular login page, open your browser's "Developer Tools" image Now login with your username, password and pass the "reCaptcha".

After login in, you can search for the entry with file = "/" in the Developer Tool's "Network"-tab image Under cookies, copy the values for both:

  • auth_tmp_token
  • c_token_valid_to

Pass these values to the application as environment variables with the same name and casing as the cookies (auth_tmp_token & c_token_valid_to).

How it works

The first time entering the checkLogin function "FIRST_TIME_LOGIN"-variable will be set to true.

Whenever FIRST_TIME_LOGIN = true, the new environment variables we just created will be read as if they were cookies and used to do a token refresh.

When a succesfull login has been done, the FIRST_TIME_LOGIN-variable will be set to false and from then on, the process should be the same as before...

image

Hello, I have Nightscout version 15.0.2 (dev branch) and I am trying to connect Carelink to Nightscout. I got the two variables from the cookies, as you explain and added them as nightscout variables, but I can't get it to connect. It gives an error in the captcha, do I need to do any additional steps?

2023-10-20T19:21:37.629584105Z stdout F '

\r\n' + 2023-10-20T19:21:37.629565525Z stdout F ' \r\n' + 2023-10-20T19:21:37.629561685Z stdout F '
\r\n' + 2023-10-20T19:21:37.629556965Z stdout F '
\r\n' + 2023-10-20T19:21:37.629552205Z stdout F '\r\n' + 2023-10-20T19:21:37.629547615Z stdout F '

Invalid recaptcha

\r\n' + 2023-10-20T19:21:37.629542785Z stdout F '\t\t\t\t
\r\n' + 2023-10-20T19:21:37.629538935Z stdout F ' \t\t\t\t\r\n' + 2023-10-20T19:21:37.629535275Z stdout F ' \t\t\t\r\n' + 2023-10-20T19:21:37.629531315Z stdout F '\t\t\t\t
\r\n' + 2023-10-20T19:21:37.629526815Z stdout F '\t\t\t\t
\r\n' + 2023-10-20T19:21:37.629521965Z stdout F ' \t\t\t\t\r\n' + 2023-10-20T19:21:37.629517305Z stdout F '\t\t\t \r\n' + 2023-10-20T19:21:37.629513055Z stdout F '
\r\n' + 2023-10-20T19:21:37.629505335Z stdout F ' \r\n' + 2023-10-20T19:21:37.629500835Z stdout F ' \r\n' + 2023-10-20T19:21:37.629488865Z stdout F ' \r\n' + 2023-10-20T19:21:37.629480845Z stdout F ' \r\n' + 2023-10-20T19:21:37.629476245Z stdout F ' <form action="https://mdtlogin-ocl.medtronic.com/mmcl/auth/oauth/v2/authorize/login?locale=en&country="; method="POST" id="form-login-en" class="form-body form-login" autocomplete="off">\r\n' + 2023-10-20T19:21:37.629471395Z stdout F '
\r\n' + 2023-10-20T19:21:37.629466525Z stdout F '
\r\n' + 2023-10-20T19:21:37.629448975Z stdout F <h1 id="title-line2" class='title-login'><span id="logo1" class="logo1">CareLink</span> <sup id="logo-tm">&trade;</sup> <span id="logo2" class="logo2"> </span></h1>\r\n + 2023-10-20T19:21:37.629443735Z stdout F <h1 id="title-line1" i18n="login_page.title_login" class='title-login'>Log in to </h1>\r\n + 2023-10-20T19:21:37.629439715Z stdout F '
\r\n' + 2023-10-20T19:21:37.629435225Z stdout F '\r\n' + 2023-10-20T19:21:37.629430655Z stdout F '
\r\n' + 2023-10-20T19:21:37.629426685Z stdout F <h1 id="banner-label" class='banner-label'><span id="banner-logo1" class="logo1">CareLink</span> <sup id="bannerlogo-tm">&trade;</sup></h1>\r\n + 2023-10-20T19:21:37.629422065Z stdout F '