Skip to content

Conversation

@m0rt4l1n
Copy link

@m0rt4l1n m0rt4l1n commented Jan 3, 2026

Update the authentication to work with the new Auth0 Authentication, see #34 and NightscoutFoundation/xDrip#4318 (reply in thread)

  • Update login script
  • Update main lib
    • Update refreshing
    • Update API Calls

@m0rt4l1n m0rt4l1n marked this pull request as ready for review January 3, 2026 00:34
@m0rt4l1n m0rt4l1n changed the title WIP: New Auth workflow fix: update to new Medtronic auth0 workflow Jan 3, 2026
@melwaraki
Copy link

Thank you! I was able to get my iOS app working thanks to your PR. 🙏

@paulobenoit
Copy link

paulobenoit commented Jan 3, 2026

great job! but I'm sure what I've to do to fix this issue ... Anyone to help me to describe how to fix this new authentification method? Thanks by advance

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 3, 2026

@paulobenoit Medtronic uses a more conventional OAuth 2.0 flow (via Auth0 SaaS) now, so this will probably make it easier on your part. I've described what the new flow looks like here NightscoutFoundation/xDrip#4318 (reply in thread)

The main change is, that you don't have to do anything before calling the /authentication endpoint and once the browser returned the access code you can directly call the /oauth/token endpoint and thats basically it. The discovery URL has also changed and now contains the key UseSSOConfiguration which selects which Key of the object you have to use for SSOConfiguration (i.e. currently Auth0SSOConfiguration)

@nightfever77
Copy link

Added the fix to my copy of the script : Login screen opens but it won't accept my credentials.

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 3, 2026

@nightfever77

Added the fix to my copy of the script : Login screen opens but it won't accept my credentials.

Thats weird, did you use the right location (if you are in the US, use the cli flag --us) and the right account? Please try to log into the Carelink connect app and online and check if it works there, if not we'll have to look into this further

@nightfever77
Copy link

Login on https://carelink.minimed.eu works, verified it before.

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 3, 2026

@nightfever77 I think it would make sense to open an issue for further discussion.
I would need some more information however:

  • Can you describe exactly what happens when you put in your username and password and press the login button (e.g. nothing happens, an error is displayed, etc.)
  • If nothing happens: in the firefox instance, that opens when you run the login script, open the developer tools and go to the networking tab, then, after entering your username & password and logging in a new (or multiple ones) entry should be visible, post a screenshot of the details (please censor the access code and other login data)

@nightfever77
Copy link

nightfever77 commented Jan 3, 2026

I type in user and password then click Login. Site refreshes and and says: incorrect username or password"

image

This is just my personal workaround for the Home Assistant integration:
As I already had a complete logindata.json file I just pasted in the new access token from the developers console (authentication via carelink.minimed.eu) and the HA integration authenticated and set up successfully.

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 3, 2026

You are somehow on the trials version of the config, I'll look into that in a bit

@nightfever77
Copy link

You are somehow on the trials version of the config, I'll look into that in a bit

That was my mistake, I missed a digit when replacing the discovery url.
Now the script runs through till the end. But every new access token expires after 3 hours.

got token data from server
{'access_token': 'xxx', 'scope': 'openid profile offline_access', 'expires_in': 10800, 'token_type': 'Bearer'}

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 3, 2026

Does the auto renewal not work for you? It is intended that the access token expires after a number of hours but the client should renew the token via the refresh_token

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 4, 2026

@nightfever77 do you use the follower account on multiple devices per chance? I think they log you out once you log in on another device

@nightfever77
Copy link

I was just reading the scripts output.
I also replaced the code in the HA integration's api.py yesterday and it is indeed working and refreshing as expected.

@meluvalli
Copy link

I'm from the US, but when I try this new login and click "Sign In", I can see FireFox twirl for a second or two, then it stops twirling and the page just sits at the Sign In screen like I didn't click the "Sign In" button. If I try to click "Sign In" again, the button appears to be disabled.

Any ideas?

I'm calling: python.exe carelink_carepartner_api_login.py --us
I have all the required add-ons installed.

It launches the FireFox window and goes to https://carelink-login.minimed.com/u/login...

My Python screen is sitting at:
Warning: you may need to close Firefox if it's already running or nothing happens!

I had this working with the old version before Medtronic changed things :(

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 5, 2026

@meluvalli could you open the Inspector (Developer tools) and look at the networking tab? After you click sign in you should see a redirect to com.medtronic.carepartner:/sso?code=<....> which the python script should detect and parse the code from.
I've tried to reproduce this with a follower account which I created in the US which worked without problems.

@meluvalli
Copy link

@m0rt4l1n When I look at the Network Tab in Dev Tools, it shows a POST login?state=.... and a GET resume?state=fs_..... However, the GET command shows: BLOCKED and the Status Code is 302. Not sure if this is part of the problem... Transferred column shows "NS_ERROR_UNKNOWN_PROTOCOL"

My python window shows:

DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): carelink.minimed.com:443
send: b'GET /configs/v1/carepartner_auth0_us_sso_config_v1.json HTTP/1.1\r\nHost: carelink.minimed.com\r\nUser-Agent: python-requests/2.31.0\r\nAccept-Encoding: gzip, deflate, br\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/json
header: Transfer-Encoding: chunked
header: Connection: keep-alive
header: Last-Modified: Mon, 15 Sep 2025 15:58:03 GMT
header: Content-Encoding: gzip
header: x-amz-server-side-encryption: aws:kms
header: x-amz-server-side-encryption-aws-kms-key-id: arn:aws:kms:us-east-1:779131433791:key/a6b2ffa3-6c5c-4aba-aa6f-38949041ff7d
header: x-amz-server-side-encryption-bucket-key-enabled: true
header: Server: AmazonS3
header: Date: Sun, 04 Jan 2026 19:07:58 GMT
header: ETag: W/"bc8267f57a89f4b8fbf808cda8fdc61a"
header: Vary: accept-encoding
header: X-Cache: Hit from cloudfront
header: Via: 1.1 f0c69aaab12c2df7a91cf822152fa666.cloudfront.net (CloudFront)
header: X-Amz-Cf-Pop: PHX50-P1
header: Alt-Svc: h3=":443"; ma=86400
header: X-Amz-Cf-Id: xqHmeftRE4wjLvN6VGXWAhe-eJDUPszK5fKrL3dZs9vqMcow00W3DA==
header: Age: 61856
DEBUG:urllib3.connectionpool:https://carelink.minimed.com:443 "GET /configs/v1/carepartner_auth0_us_sso_config_v1.json HTTP/1.1" 200 None
opening Firefox instance...
Warning: you may need to close Firefox if it's already running or nothing happens!
INFO:seleniumwire.storage:Using default request storage
INFO:seleniumwire.backend:Created proxy listening on 127.0.0.1:50849
DEBUG:selenium.webdriver.common.selenium_manager:Selenium Manager binary found at: C:\Users\Aaron\AppData\Roaming\Python\Python313-32\site-packages\selenium\webdriver\common\windows\selenium-manager.exe
DEBUG:selenium.webdriver.common.selenium_manager:Executing process: C:\Users\Aaron\AppData\Roaming\Python\Python313-32\site-packages\selenium\webdriver\common\windows\selenium-manager.exe --browser firefox --proxy 127.0.0.1:50849 --debug --language-binding python --output json
DEBUG:seleniumwire.server:127.0.0.1:50852: clientconnect
DEBUG:seleniumwire.server:127.0.0.1:50852: Set new server address: plausible.io:443
DEBUG:seleniumwire.server:127.0.0.1:50852: TcpException('Error connecting to "plausible.io": [Errno 11004] getaddrinfo failed')
DEBUG:seleniumwire.server:127.0.0.1:50852: Establish TLS with client
DEBUG:seleniumwire.server:127.0.0.1:50853: clientconnect
DEBUG:seleniumwire.server:127.0.0.1:50853: Set new server address: raw.githubusercontent.com:443
DEBUG:seleniumwire.server:127.0.0.1:50853: serverconnect
  -> ('raw.githubusercontent.com', 443)
DEBUG:seleniumwire.server:127.0.0.1:50853: Establish TLS with server
DEBUG:seleniumwire.server:127.0.0.1:50852: ALPN for client: b'http/1.1'
DEBUG:seleniumwire.server:127.0.0.1:50852: clientdisconnect
DEBUG:seleniumwire.server:127.0.0.1:50853: ALPN selected by server: http/1.1
DEBUG:seleniumwire.server:127.0.0.1:50853: Establish TLS with client
DEBUG:seleniumwire.server:127.0.0.1:50853: ALPN for client: b'http/1.1'
DEBUG:seleniumwire.server:127.0.0.1:50853: request
  -> Request(GET /SeleniumHQ/selenium/trunk/common/geckodriver/geckodriver-support.json)
INFO:seleniumwire.handler:Capturing request: https://raw.githubusercontent.com/SeleniumHQ/selenium/trunk/common/geckodriver/geckodriver-support.json
DEBUG:seleniumwire.server:127.0.0.1:50853: response
  -> Response(200, text/plain; charset=utf-8, 2.81k)
INFO:seleniumwire.handler:Capturing response: https://raw.githubusercontent.com/SeleniumHQ/selenium/trunk/common/geckodriver/geckodriver-support.json 200 OK
DEBUG:seleniumwire.server:127.0.0.1:50853: serverdisconnect
  -> ('raw.githubusercontent.com', 443)
DEBUG:selenium.webdriver.common.selenium_manager:Using proxy: 127.0.0.1:50849
DEBUG:seleniumwire.server:127.0.0.1:50853: clientdisconnect
DEBUG:selenium.webdriver.common.selenium_manager:Sending stats to Plausible: Props { browser: "firefox", browser_version: "", os: "windows", arch: "x86_64", lang: "python", selenium_version: "4.39" }
DEBUG:selenium.webdriver.common.selenium_manager:geckodriver not found in PATH
DEBUG:selenium.webdriver.common.selenium_manager:firefox detected at C:\Program Files\Mozilla Firefox\firefox.exe
DEBUG:selenium.webdriver.common.selenium_manager:Detected browser: firefox 134.0
DEBUG:selenium.webdriver.common.selenium_manager:Valid geckodriver versions for firefox 134: ["0.36.0", "0.35.0", "0.34.0"]
DEBUG:selenium.webdriver.common.selenium_manager:Required driver: geckodriver 0.36.0
DEBUG:selenium.webdriver.common.selenium_manager:geckodriver 0.36.0 already in the cache
DEBUG:selenium.webdriver.common.selenium_manager:Driver path: C:\Users\Aaron\.cache\selenium\geckodriver\win64\0.36.0\geckodriver.exe
DEBUG:selenium.webdriver.common.selenium_manager:Browser path: C:\Program Files\Mozilla Firefox\firefox.exe
DEBUG:selenium.webdriver.common.service:Started executable: `C:\Users\Aaron\.cache\selenium\geckodriver\win64\0.36.0\geckodriver.exe` in a child process with pid: 3504 using 0 to output -3
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:50850/session {'capabilities': {'firstMatch': [{}], 'alwaysMatch': {'browserName': 'firefox', 'acceptInsecureCerts': True, 'moz:debuggerAddress': True, 'pageLoadStrategy': <PageLoadStrategy.normal: 'normal'>, 'proxy': {'proxyType': 'manual', 'httpProxy': '127.0.0.1:50849', 'sslProxy': '127.0.0.1:50849'}, 'browserVersion': None, 'moz:firefoxOptions': {'binary': 'C:\\Program Files\\Mozilla Firefox\\firefox.exe', 'prefs': {'remote.active-protocols': 1, 'network.proxy.allow_hijacking_localhost': True}}}}}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:50850
send: b'POST /session HTTP/1.1\r\nHost: localhost:50850\r\nAccept-Encoding: identity\r\nContent-Length: 465\r\nAccept: application/json\r\nContent-Type: application/json;charset=UTF-8\r\nUser-Agent: selenium/4.39.0 (python win32)\r\nConnection: keep-alive\r\n\r\n'
send: b'{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"browserName": "firefox", "acceptInsecureCerts": true, "moz:debuggerAddress": true, "pageLoadStrategy": "normal", "proxy": {"proxyType": "manual", "httpProxy": "127.0.0.1:50849", "sslProxy": "127.0.0.1:50849"}, "browserVersion": null, "moz:firefoxOptions": {"binary": "C:\\\\Program Files\\\\Mozilla Firefox\\\\firefox.exe", "prefs": {"remote.active-protocols": 1, "network.proxy.allow_hijacking_localhost": true}}}}}'
reply: 'HTTP/1.1 200 OK\r\n'
header: content-type: application/json; charset=utf-8
header: cache-control: no-cache
header: content-length: 878
header: date: Mon, 05 Jan 2026 12:18:58 GMT
DEBUG:urllib3.connectionpool:http://localhost:50850 "POST /session HTTP/1.1" 200 0
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":{"sessionId":"db8be3b4-a6f3-4826-9470-a33697e9b8f5","capabilities":{"acceptInsecureCerts":true,"browserName":"firefox","browserVersion":"134.0","moz:accessibilityChecks":false,"moz:buildID":"20241230151726","moz:geckodriverVersion":"0.36.0","moz:headless":false,"moz:platformVersion":"10.0","moz:processID":11168,"moz:profile":"C:\\Users\\Aaron\\AppData\\Local\\Temp\\rust_mozprofile1bYtVv","moz:shutdownTimeout":60000,"moz:webdriverClick":true,"moz:windowless":false,"pageLoadStrategy":"normal","platformName":"windows","proxy":{"httpProxy":"127.0.0.1:50849","proxyType":"manual","sslProxy":"127.0.0.1:50849"},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0"}}} | headers=HTTPHeaderDict({'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-cache', 'content-length': '878', 'date': 'Mon, 05 Jan 2026 12:18:58 GMT'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request
DEBUG:selenium.webdriver.remote.remote_connection:POST http://localhost:50850/session/db8be3b4-a6f3-4826-9470-a33697e9b8f5/url {'url': 'https://carelink-login.minimed.com:443/authorize?client_id=0FGoNwY0SP8ZmESYSfEOgMw03c58c1hk&response...'}
send: b'POST /session/db8be3b4-a6f3-4826-9470-a33697e9b8f5/url HTTP/1.1\r\nHost: localhost:50850\r\nAccept-Encoding: identity\r\nContent-Length: 233\r\nAccept: application/json\r\nContent-Type: application/json;charset=UTF-8\r\nUser-Agent: selenium/4.39.0 (python win32)\r\nConnection: keep-alive\r\n\r\n'
send: b'{"url": "https://carelink-login.minimed.com:443/authorize?client_id=0FGoNwY0SP8ZmESYSfEOgMw03c58c1hk&response_type=code&scope=profile openid offline_access&redirect_uri=com.medtronic.carepartner:/sso&audience=carepartner.patient.us"}'
reply: 'HTTP/1.1 200 OK\r\n'
header: content-type: application/json; charset=utf-8
header: cache-control: no-cache
header: content-length: 14
header: date: Mon, 05 Jan 2026 12:19:04 GMT
DEBUG:urllib3.connectionpool:http://localhost:50850 "POST /session/db8be3b4-a6f3-4826-9470-a33697e9b8f5/url HTTP/1.1" 200 0
DEBUG:selenium.webdriver.remote.remote_connection:Remote response: status=200 | data={"value":null} | headers=HTTPHeaderDict({'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-cache', 'content-length': '14', 'date': 'Mon, 05 Jan 2026 12:19:04 GMT'})
DEBUG:selenium.webdriver.remote.remote_connection:Finished Request

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 5, 2026

The 302 is supposed to happen, please check if the location header is of the following format:

screenshott

If this is right, please check that you are using the newest version of this branch and that you don't have any local changes present (to be sure, just clone the repo again and checkout this PR)

If this still doesn't work, add print(f"redirected to: {location}") after location = request.response.headers["location"] in carelink_carepartner_api_login.py and post the lines starting with redirected to (please redact the states and code)
This should result in a bunch of lines starting redirected to: /u/login?state=, redirected to: /authorize/resume?state=? but finally one that is redirected to: com.medtronic.carepartner:/sso?code=

@ondrej1024
Copy link
Owner

@m0rt4l1n : I noticed you kept the old do_login function (renamed to do_login_non_auth0) and use it if the UseSSOConfiguration key value does not contain "Auth0".

Do you think this is still needed? And would this even work?

@m0rt4l1n
Copy link
Author

m0rt4l1n commented Jan 5, 2026

@m0rt4l1n : I noticed you kept the old do_login function (renamed to do_login_non_auth0) and use it if the UseSSOConfiguration key value does not contain "Auth0".

Do you think this is still needed? And would this even work?

IMO it is very unlikely the old login stuff will be needed anytime soon. I think we can also rename the auth0 stuff to just oauth, as most of the login stuff is very generic to just oauth.

I didn't have time yet to improve the code quality, I'll try to do this today or tomorrow so this PR becomes mergable :)

@meluvalli
Copy link

@m0rt4l1n I finally figured it out. I was running FireFox 145.0. I uninstalled it, reinstalled it and same thing. So, I checked what the latest version was and it's 146.0.1. I uninstalled 145.0, installed 146.0.1, and voila! It worked now!

I don't know why I had to upgrade to 146.0.1 to make it work?

I installed my plugins like so:

"%PythonFolder%\python.exe" -m pip install requests==2.31.0
"%PythonFolder%\python.exe" -m pip install curlify==2.2.1
"%PythonFolder%\python.exe" -m pip install pyOpenSSL==24.0.0
"%PythonFolder%\python.exe" -m pip install selenium-wire==5.1.0
"%PythonFolder%\python.exe" -m pip install setuptools
"%PythonFolder%\python.exe" -m pip install packaging
"%PythonFolder%\python.exe" -m pip install webdriver-manager
"%PythonFolder%\python.exe" -m pip install blinker==1.7.0

So, selenium is forced at the version I was using before. Any ideas why I would have had to upgrade FireFox to make it work? (Just for my own curiosity)

Thank you for your help!!!

@ondrej1024
Copy link
Owner

The script carelink_carepartner_api_login.py has been causing headaches for a lot of people (see various issues reported in this repo). It has a lot of dependencies which are also different depending on the OS you are running it on.

Unfortunately the initial login procedure needs to resolve the Capcha challenge on the Carelink web page and therefore needs a GUI. But carelink-python-client being an application which mainly runs on headless systems cannon provide that. So this seperate login script is provided to do just that.

I have always wondered if there is a better way of doing that. One idea that came to my mind is that a mobile app could be implemented doing the same thing. And thinking some more about this, there already is an app which implements the login procedure, and that is xDrip. Maybe an option could be added to xDrip to export the login data and create the logindata.json file we need. I think this would be an easy alternative to using the Python script.

@meluvalli
Copy link

What made me figure out part of the problem was when m0rt4l1n told me "add print(f"redirected to: {location}") after location = request.response.headers["location"]". I did this and nothing was printing on the screen... So I knew Selenium wasn't talking to FireFox correctly...

Nonetheless, I appreciate the time and effort of this script! I thank you!

@palmarci
Copy link
Contributor

palmarci commented Jan 6, 2026

Hello guys! I just want to thank you for still maintaining and updating this. I need to take a second look at the APIs for the pump pairing process ;) . The branch works flawlessly for me.

@odiak
Copy link

odiak commented Jan 8, 2026

Though it’s off topic, I haven’t seen a CAPTCHA on the Carelink login page recently.
Is it just me?

@ondrej1024
Copy link
Owner

Though it’s off topic, I haven’t seen a CAPTCHA on the Carelink login page recently. Is it just me?

You are right. I just checked and no CAPTCHA appears on the login page at the moment. But this is probably a temporary glitch. Medtronic might have accidentally removed it and it could be back any time.

Looks like there is maintenance activity planned for 13-01-2026 on the Carelink server. Let's wait and see what surprises we'll get 😟

@odiak
Copy link

odiak commented Jan 8, 2026

Actually, I haven't seen CAPTCHA since last October. 😂

@ondrej1024
Copy link
Owner

I didn't have time yet to improve the code quality, I'll try to do this today or tomorrow so this PR becomes mergable :)

@m0rt4l1n
I haven't seen any issues with this PR so far. My carelink_client2_proxy.py has been running for a week with the fix now and things are looking good. So as soon as you have some time to do the code cleanup we discussed above, we can proceed with merging this. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants