-
Notifications
You must be signed in to change notification settings - Fork 424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JWT is not well formed, there are no dots #1111
Comments
Hi, I’ll have some time next week to investigate. I’ll report back. Never happened this to me before nor anyone reported this earlier. |
I’ve previously seen this issue logged, similar error, different situation I think - #998 |
The problem seems to be that oauthlib is no longer caching the correct error codes MS Graph gives and thus giving apps error codes like 401 (unauthorised) when it should raise From my end this is difficult to solve as O365 don't know if a 401 is returned because the token is expired and oauthlib didn't do it's work raising the TokenExpiredError or it's actually a unauthorised error that is correct. So, either anyone solves this inside oauthlib (which I think should be very difficult) or O365 drops it's custom auth methods to use msal. I would go wih msal, but this is a BIG change that touches many 'moving parts'. |
I’m not sure I have the knowledge to rework the auth method, but I can take a look when I get back home next week. In the interim, presumably I can trap the errors in my integration and trigger a token refresh? |
The current quick solution involves the following (other users reported this several times here):
|
Thanks |
And please remember that the refresh should ask before to the token backed: should_refresh_token = self.token_backend.should_refresh_token(self)
if should_refresh_token is True:
# The backend has checked that we can refresh the token
if self.refresh_token() is False:
raise RuntimeError('Token Refresh Operation not working') Although |
I have analysed what it means to implement authentication with MSAL.
I have been able to authenticate and use a O365 with tokens retrieved using msal. I think I will drop custom auth in favor of msal as soon as possible |
That would be brilliant. I'd be happy to test as soon as you have something (preferably not before the 23rd, if it requires code change at my end). |
I will be working in the msal branch |
Not sure on the notes you have written on the meal branch whether you have finished work and it is testable, our whether it is WUP. I see you have note that 2.0.38 is the last 2.0 release, which suggests you will go to 2.1/3.0 for new authentication model. As soon as you are ready I can test. |
It is difficult to integrate between both without breaking changes. I really don't know if it will be possible without a huge amount of efford |
No problem. If it isn't possible, then I understand. If you can do it, I think it is the right thing to do. I'm buried at the moment, but I can also take a look, probably in the New Year. However, I suspect if you can't do it, no-one can. I'd be coming at it with inexperienced eyes with regards OAUTH. |
This looks weird to me. Any of those parms (jwt, top, startDateTime, endDateDateTime, … ) should be posted and not included in the url. I am not sure if this error has anything to do with the JWT token. The dot within the StartDateTime looks even more strange. Could it be the case that it's just a bad error message from the backend and is not related to the token itself? |
For me it's very difficult to test this. I don't see this error anywhere in my tests.... @RogerSelwyn I'm 75% done with the use of msal. For example: users already authenticated will need to re-authenticate as the stored tokens are no longer valid in their current form. In the msal branch you can currently do all except that the requests will stop working after 1 hour as I haven't yet changed the refresh token methods. So:
|
Btw! When it's expired it returns: This is nonsense... and is also a problem with msal use. |
That sounds like amazing progress. For me it seems likely it will not be a major impact if people need to re-authenticate. Firstly I’m at a changeover point from one code set to a new one, so people are doing a new setup anyway. Secondly I’ve made the management of re-authentication simpler. I’ll try to test with the code base when I get home, may not be until Wednesday. |
Is this a change you are now including into the code? It is it already there? |
I'm doing it atm. I will probably finish it tomorrow. Then I'll need some help running some tests. I will be glad if you can help me there. Thanks |
I’m away, may be able to test Sunday/Monday. |
Done!, It works and refreshes and everything as before. I'll implement "multi-account" authentication next, as until now 1 account instance can only hold 1 authentication, Now it can hold as many as you want |
Done as well. After the testing I will release asap |
When I try to authenticate I get this error. Do you no longer need
|
Yes, remove it |
If I remove offline_access, which I think is not needed any more I get this error.
Do you need for me to pull something else out of that call? |
What auth_flow_type are you using? |
I don't pass any flow type to Account setup, so I believe it is "authorization". |
Yes it is by default. Mmm can you just give me the "simplified" code used until the error? |
In the call at 587:
|
Mmm ok, I think I know what’s happening there. I’ll add a check to see if the token data is the old one and if it is will not load that token data in. |
I'm getting this error after some time, so I'm guessing it is token refresh related. I'll try to dig into it.
|
The error occurs at startup. The parameters in at line 680 are:
Not sure why scopes is empty. My call in that triggered the error is Previous calls, were:
I can do an alternate call if needed. EDIT: If I add scopes into the call to Account setup it seems to work. Didn't need to do this before, but it's not a problem. |
Just to add, I've had to modify some of my tests because of the changes in your code, but they are running fine. Just the issue above around refreshing the token. |
I've done the following:
|
I don't know why self.scopes is None. For me it's not None. It can't be None as scopes are required. It will raise an error if they are not set in the call to Can you please see where is connection.scopes None? |
There is no call to account.authenticate() in the sequence where authentication has previously occurred and it's working from a stored token, which it is now trying to refresh because it has expired. So the scenario is, I have previously authenticated and retrieved my token, which is stored in a file location. My application is then re-started, I don't need to call account.authenticate(), because I give O365 the token to use. So the calls I make are:
None of these calls require the scope to be passed in.
I had assumed that because the token is passed into Account setup, that the scope would be retrieved from there, but I can't see anything that would so that. I'll try to have my test environment running at the point at which it would refresh the token after it expiring during normal running, to see if I get the same error there. I had anticipated that if I had passed in the token, it would retrieve the scopes from there. Not a major problem because I can pass them in at Account setup, but if it is mandatory, then it should be modified to make sure it is provided. |
The same thing happens. So I guess you either need to pass scopes into Account setup, or being doing an account.authenticate(). I don't think you will do .authenticate() more than once (certainly not after every app startup), so scopes need to be passed into Account, then it will get a new access token using the refresh token. |
I'll try these out over the next couple of days. |
ok, but before this change you had to always pass the scopes anyway into the connection (with or without token stored). I can of course get the scopes stored from the token and then pass them into the auth calls anyway, but it wasn't working this way previously. Although maybe python oauthlib was doing something under the hood I was not aware of... I can change it so when there are no scopes defined, but there is a token stored we can get the scopes from the token, ignoring any scopes passed. So scopes are only needed when authenticating. |
No, I didn't pass scopes into Account setup before. But I can do easily.
Up to you, it is more changes for people using the library. |
I've done it. Can you test it please? Thanks a lot |
This change now causes the following error:
I was passing in scopes as |
Will do. Need to wait for token to expire. |
??? Scope is now never a tuple. It was when offline_access was in it. Now I removed all checks of scope being a tuple. |
Found it and fix it! Sorry |
I have a busy day tomorrow, so may not get to do any testing. Should get some time Wednesday. |
Whenever you can, thanks |
I’ve tested most things. The method to retrieve the scopes is too complex to include at the right point in my code. The method isn’t complex, just providing the right info to it (username) at the point I need the info. So I haven’t tested it. Token refresh seems to be working, based on me not supplying scopes to account setup, so you retrieving it seems to be working fine. Next step for me would be to trial on my production environment, but could do with a pip package for that. |
Actually I think I can test it in production without pip package. I’ll try in the next couple of days. |
Mind that passing the username is optional. Most users will only have 1 auth stored (1 user). If you don’t pass the username, the info retrieved will be the one for the first username found. Since most people will one have 1 auth this is completely transparent. Nevertheless I will set a method inside account to retrieve all the users authenticated, but as I said this will only affect a small user base. Also mind that this is how msal works so I have to provide a username always and O356 does it in a way that is transparent for the users. Also I have included this info in the readme of the msal branch. |
I'll try it again, I think when I tried with no username I got nothing back, but it would have been before I did account setup. Been a long day today, so it won't be until tomorrow. I tried it based on just FileSystemTokenBackend setup. But I was fighting another issue, so I didn't try too hard. |
I've tested So I think I can test as much as I can. My full pytest suite tests using mocked ms graph api responses, but should be reasonably good. Also I've run in my dev environment for some hours and it seems to be handling refreshes fine. Do you want me to test in my prod, before you release or are you happy with it? |
I’m more worried for the people using credentials auth flow type. I think we can release it as it is and iterate over. |
Not sure I can meaningfully test that since I don't use it. I could possibly work out how to use it, might take a while though. |
Do you have an idea as to when you will release? |
Soon! |
You have written this in the readme I don't think you can add
|
retreive the state saved in auth_step_one - |
I think I have a problem where if I try to retrieve a new token (because I can change scope news within the app while it is running), when I already have an existing one, then it returns the existing token. I think it returns it from the cache, because before I do the call to '.request_token` I've just added a process to delete the stored file token. So steps:
|
I have a few people who use the Home Assistant O365 integration that are getting the errors as shown below (they are encapsulated in HA login, but you can see what is being surfaced by O365). I've only seen reports in the last few months, but I have no idea what is causing them. Unfortunately I don't get the problem myself (or just don't notice the error in my logs, so I don't really know what triggers it).
Any ideas as to what is causing the problem? The integration sets up a FileSystemTokenBackend, which it uses I the Account setup call, beyond that it leaves token management to O365 (apart from reading the token once to check granted permissions). Code as below:
Client Error: 401 Client Error: Unauthorized for url: https://graph.microsoft.com/v1.0/me/calendars/AQMkADAwATNiZmYAZC04M2ZhLTkwNDYtMDACLTAwCgBGAAADxUpIqt1PQ02qEe37a0cywQcAe9JyutQAp0a3sg19Hw9tFgAAAgEGAAAAe9JyutQAp0a3sg19Hw9tFgAF1RvVAwAAAA==/calendarView?%24top=999&startDateTime=2024-11-08T07%3A48%3A44.399251%2B00%3A00&endDateTime=2024-11-09T07%3A48%3A44.399274%2B00%3A00&%24select=sensitivity%2Cstart%2Ccategories%2Cbody%2CisAllDay%2Csubject%2Cend%2Clocation%2CseriesMasterId%2Cattendees%2CshowAs | Error Message: IDX14100: JWT is not well formed, there are no dots (.). The token needs to be in JWS or JWE Compact Serialization Format. (JWS): 'EncodedHeader.EncodedPayload.EncodedSignature'. (JWE): 'EncodedProtectedHeader.EncodedEncryptedKey.EncodedInitializationVector.EncodedCiphertext.EncodedAuthenticationTag'. | Error Code:
The user has checked their access token. There are no dots inside. They've also checked it with jwt.io and get the following error:
Error: Looks like your JWT Header is not encoded correclty using base64url (https://tools.ietf.org/html/rfc4648#section-5). Note that padding ("=") must be omitted as per https://tools.ietf.org/html/rfc7515'section-2
The error does not occur permanently, but only occasionally. It then seems to heal itself, since the synchronization of tasks and calendar generally works.
The text was updated successfully, but these errors were encountered: