mattermost / mattermost-mobile

Next generation iOS and Android apps for Mattermost in React Native
https://about.mattermost.com/
Apache License 2.0
2.25k stars 1.36k forks source link

Profile picture doesn't show if SSO #4486

Closed bill2004158 closed 1 year ago

bill2004158 commented 4 years ago

Summary

profile picture doesn't show when SSO.

Environment Information

Steps to reproduce

  1. sso login (gitlab)
  2. and then check profile picture

Expected behavior

show profile picture

Observed behavior

the http request:

GET https://mm.test.domain/mm/api/v4/users/67um3oztnp8n8yexu1wdkjju7c/image HTTP/1.1
Host: mm.test.domain
Accept: image/*,*/*;q=0.8
Accept-Language: en-us
Connection: keep-alive
Accept-Encoding: gzip, deflate, br
User-Agent: Mattermost/1.32.0 (iPhone; iOS 13.2.2; Scale/2.00)

response:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
Expires: 0
Vary: Accept-Encoding
X-Request-Id: hhzpbu8617ropcu351nb4zwefo
X-Version-Id: 5.21.0.5.21.0.d034a3d0686bcd932fa7681706e0c3f1.false
X-Powered-By: ARR/3.0
X-Powered-By: ASP.NET
Date: Fri, 26 Jun 2020 08:19:39 GMT
Content-Length: 186

{"id":"api.context.session_expired.app_error","message":"Invalid or expired session, please login again.","detailed_error":"","request_id":"hhzpbu8617ropcu351nb4zwefo","status_code":401}

Possible fixes

go to app\components\profile_picture\profile_picture.js change:

source = {
                uri: `${prefix}${pictureUrl}`,
            };

to

source = {
                uri: `${prefix}${pictureUrl}`,
                headers: {Authorization: `BEARER ${Client4.token}`},
            };
enahum commented 4 years ago

Anything in your server deployment that could prevent it from setting the authorize cookies?

bill2004158 commented 4 years ago

I am not sure, will check that.

bill2004158 commented 4 years ago

@enahum , in android, authorize cookie is included. however, not sure why in ios (I am testing using simulator), it doesn't include authorize cookies, but only "Authorization: BEARER dwnth4ggyfdbiph9wznpopzsph".

the test details: req:

GET https://demo.domain.com/mm/signup/gitlab/complete?code=EDzUrEFKOiwnducq&state=eyJhY3Rpb24iOiJtb2JpbGU HTTP/1.1

response:

HTTP/1.1 200 OK
Content-Type: application/json
Expires: 0
Vary: Accept-Encoding
Set-Cookie: MMOAUTH=; Path=/mm; Max-Age=0; HttpOnly
Set-Cookie: MMAUTHTOKEN=dwnth4ggyfdbiph9wznpopzsph; Path=/mm; Expires=Thu, 24 Dec 2020 06:09:58 GMT; Max-Age=15552000; HttpOnly
Set-Cookie: MMUSERID=74zbij7o93b49f9xk8tqcmkn9a; Path=/mm; Expires=Thu, 24 Dec 2020 06:09:58 GMT; Max-Age=15552000
Set-Cookie: MMCSRF=rif56okzgtf7my333ow8tph18r; Path=/mm; Expires=Thu, 24 Dec 2020 06:09:58 GMT; Max-Age=15552000

and the next request:

GET https://demo.domain.com/mm/api/v4/users/me HTTP/1.1
Host: demo.domain.com
Content-Type: 
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
Accept-Language: en
Authorization: BEARER dwnth4ggyfdbiph9wznpopzsph
x-requested-with: XMLHttpRequest

resp:

HTTP/1.1 200 OK
Content-Type: application/json
Expires: 0
ETag: 5.21.0.74zbij7o93b49f9xk8tqcmkn9a.1592986647087..0.true.true.0
Vary: Accept-Encoding
X-Request-Id: pok6nc8hj3fhifrzqerxd7q7sh
X-Version-Id: 5.21.0.5.21.0.d034a3d0686bcd932fa7681706e0c3f1.false
X-Powered-By: ARR/3.0
X-Powered-By: ASP.NET
Date: Sat, 27 Jun 2020 06:10:03 GMT
Content-Length: 655

{"id":"74zbij7o93b49f9xk8tqcmkn9a","create_at":1591585153240 ... }

it seems Set-Cookie doesn't works for iOS?

bill2004158 commented 4 years ago

tried latest rev of branch release_1.32, I got same issue.

enahum commented 4 years ago

Do you get the same result using the app from the app store?

bill2004158 commented 4 years ago

@enahum , I found something maybe related to this issue from reactnative.dev: As a minimum on iOS, when redirected through a 302, if a Set-Cookie header is present, the cookie is not set properly. Since the redirect cannot be handled manually this might cause a scenario where infinite requests occur if the redirect is the result of an expired session. ref: https://reactnative.dev/docs/network#known-issues-with-fetch-and-cookie-based-authentication

in our case: when sso, the gitlab server send response:

HTTP/1.1 302 Found
Content-Type: text/html; charset=utf-8
Location: https://demo.domain.com/mm/signup/gitlab/complete?code=daL9QY4kt3DqCsjF&state=eyJhY3Rpb24iOiJtb2JpbGU

after authenticated, which redirect back to mattermost server. and then mattermost server will process /signup/gitlab/complete, and Set-Cookie.

so it seems that doc explained why Set-Cookie not work?

bill2004158 commented 3 years ago

@enahum , it is same issue that cannot preview the image if someone send a image in channel. (only effect iOS)

and I have found out the issue finally. https://github.com/mattermost/mattermost-mobile/blob/master/app/screens/sso/sso.js#L120 CookieManager.get(url, true) --> the second parameter true, means get cookie from WKWebsiteDataStore.defaultDataStore.httpCookieStore which is cookie store of the the WebView.

however, after sso login, mattermost will dispose that webview, of course those cookies (MMAUTHTOKEN, MMCSRF) will be disappear. when display image, react-native-fast-image will download the image using the cookies from NSHTTPCookieStorage.sharedHTTPCookieStorage which doesn't have MMAUTHTOKEN!

that is why the image downloaded fail, of course, the images cannot be shown.

so after sso login, we need copy the cookies to NSHTTPCookieStorage.sharedHTTPCookieStorage.

enahum commented 3 years ago

@bill2004158 That is in fact a nice theory, but I wonder why does it work for every MM staff members that signs in to the community server using SSO, the same can be said of every customer that uses SSO to login to the mobile app.

bill2004158 commented 3 years ago

@enahum

doc from apple: https://developer.apple.com/documentation/foundation/nshttpcookiestorage Each app and app extension has a unique data container, meaning they have separate cookie stores. WKWebView — Each WKWebView instance has its own cookie storage. See the WKHTTPCookieStore class for more information.

I am not sure why it works for you. can you show me the code when the cookie MMAUTHTOKEN is coped from WKHTTPCookieStore to sharedHTTPCookieStorage? or can you explain how your image preview request get authenticated by mattermost.

in my case, the preview request doesn't have MMAUTHTOKEN in the cookie if I didn't copy it after sso.

enahum commented 3 years ago

@bill2004158 After the user successful authentication, this is being set https://github.com/mattermost/mattermost-mobile/blob/master/app/screens/sso/sso.js#L137

Basically the token gets set for the client to execute further autenthicated requests. Once the first response comes in RNFetchBlob which is the library that we use, will set the cookies here https://github.com/joltup/rn-fetch-blob/blob/master/ios/RNFetchBlobRequest.m#L256

bill2004158 commented 3 years ago

@enahum , that is for reply.

After the user successful authentication, this is being set https://github.com/mattermost/mattermost-mobile/blob/master/app/screens/sso/sso.js#L137 --> yes, that set the token to Client4, however, some requests (such as preview image) is not send from Client4.

Once the first response comes in RNFetchBlob which is the library that we use, will set the cookies here https://github.com/joltup/rn-fetch-blob/blob/master/ios/RNFetchBlobRequest.m#L256 --> yes, that the code sync cookie. however, /signup/gitlab/complete (which repose the MMAUTHTOKEN) is sent by WebView, will the reponse be processed by rn-fetch-blob?

enahum commented 3 years ago

@bill2004158 yes the images are not being requested from Client4 and in consequence without RNFetchBlob.

That said, the first request after a successful login is executed here https://github.com/mattermost/mattermost-mobile/blob/86ae89d3eb6d8fdee8804eb58d0bacbb7f36da37/app/actions/views/user.js#L190 and that will then generate requests to the endpoints found in this action function https://github.com/mattermost/mattermost-mobile/blob/86ae89d3eb6d8fdee8804eb58d0bacbb7f36da37/app/actions/views/user.js#L80

Those request are performed by the Client4 which uses RNFetchBlob, as soon as the first response gets in, the cookies in that response are being set, which includes MMAUTHTOKEN if I'm not mistaken, then the NSConnectionURL used by fast-image will use the cookies that were set by rn-fetch -blob

bill2004158 commented 3 years ago

@enahum ,

ah, I see. in my server, the first request of loadMe() is Get api/v4/users/me. which response: HTTP/1.1 304 Not Modified Expires: 0 ETag: 5.27.0.cimdxwxz7pys5png1p465ta5kc.1598861638199..0.true.true.0 Vary: Accept-Encoding X-Request-Id: u9qwekhtsfrixjed7smupi7pzo X-Version-Id: 5.27.0.5.27.0.94bf8d3f894ad10e1a0aa6fc0ee3c179.false X-Powered-By: ARR/3.0 X-Powered-By: ASP.NET Date: Fri, 08 Jan 2021 15:29:40 GMT

it seems there is some issue in that reponse, which should set cookie MMAUTHTOKEN.

thanks for reply, I will check our server side.

svenseeberg commented 2 years ago

Was anybody able to solve this by changing the server configuration? If yes, what was changed? However there must be something special about the app, because Mattermost works without problems in a browser.

bill2004158 commented 2 years ago

@svenseeberg, as I explain above, the main problem, the mobile app, used WebView & RNFetchBlob for communicate with server, thus the cookie(MMAUTHTOKEN) is stored in different location.
(which doesn't have this issue for browser) we just "copy the cookies to NSHTTPCookieStorage.sharedHTTPCookieStorage" after sso login, that resolve the issue for our case. we didn't change anything at server side.

as @enahum said "as soon as the first response gets in, the cookies in that response are being set, which includes MMAUTHTOKEN". unluckily, in our server, which doesn't set that cookie for that response. I haven't have chance to review the server side yet.

christianhueserhzdr commented 2 years ago

Dear @bill2004158, that's really great to read that there is an explanation for this behaviour and a proposed solution. Many thanks for taking the time to pin down what is going wrong here. Do you think this could eventually be resolved at some point? It would be great to have images, avatars and icons working for all users. Would it be possible to assign this issue to someone who is able to fix this? A fix would be much appreciated. Thank you very much in advance for your response!

christianhueserhzdr commented 2 years ago

Dear @enahum, since @bill2004158 reported this issue only and seems not to be a contributor yet, maybe you could give an estimation on what it takes to fix this issue and how long it could take? Do you have people working in it already? Thank you very much in advance for your response!

enahum commented 2 years ago

Hi @christianhueserhzdr sadly this is not something that we are actively looking at, the reality is that since this issue was opened, it looks like the affected deployments are not many in comparison with the amount of deployments that use SSO, which leads me to believe this is not really about the app but perhaps something in a reverse proxy or something.

On the other hand, the team full focus is on the mobile v2 app which is now in beta and you can enroll to give it a try by following the instructions in the README file on this repo. Perhaps you would want to give that a try, and in case you are still seeing the issue while using mobile v2 we can start looking into it.

Thanks.

christianhueserhzdr commented 2 years ago

Hi @christianhueserhzdr sadly this is not something that we are actively looking at, the reality is that since this issue was opened, it looks like the affected deployments are not many in comparison with the amount of deployments that use SSO, which leads me to believe this is not really about the app but perhaps something in a reverse proxy or something.

On the other hand, the team full focus is on the mobile v2 app which is now in beta and you can enroll to give it a try by following the instructions in the README file on this repo. Perhaps you would want to give that a try, and in case you are still seeing the issue while using mobile v2 we can start looking into it.

Thanks.

Dear Elias @enahum, many thanks for your estimation. I will give mobile v2 app a try. Great that the team is eagerly working on it! I will let you know if this issue is resolved in that new version.

maxammann commented 2 years ago

Just tested the latest Beta. Problem still persists.

enahum commented 2 years ago

@anurag6713 can you take a look into this?

svenseeberg commented 2 years ago

it looks like the affected deployments are not many in comparison with the amount of deployments that use SSO, which leads me to believe this is not really about the app but perhaps something in a reverse proxy or something.

I agree that this sounds likely. However, we already compared our configuration multiple times with the documentation and could not find any issues. We are using Gitea as an IdP instead of Gitlab. I was not yet able to determine if or why this would make a difference.

tralston commented 2 years ago

it looks like the affected deployments are not many in comparison with the amount of deployments that use SSO, which leads me to believe this is not really about the app but perhaps something in a reverse proxy or something.

I agree that this sounds likely. However, we already compared our configuration multiple times with the documentation and could not find any issues. We are using Gitea as an IdP instead of Gitlab. I was not yet able to determine if or why this would make a difference.

@svenseeberg @enahum

Just wanted to add some extra data to the issue. We are a corporate customer, on Enterprise Cloud. This affects us too. There's nothing I can do about our server config or reverse proxies, because that's all configured at MM. On my own iPad (company managed) I was having the same problem, and I logging out/in didn't work. But removing the app, then reinstalling and logging in worked. That must be enough to clear out any problematic caches.

I'm glad it works, but I'm wondering if there is a path forward knowing this? We're bound to have more issues with this (even if in a small fraction of users). Thanks for all your hard work!

svenseeberg commented 2 years ago

But removing the app, then reinstalling and logging in worked.

Just want to add that this does not work for me. The issue persists after reinstalling the app.

larkox commented 1 year ago

@svenseeberg Any chance you can try with the latest beta (V2) and see if the issue still persist?

svenseeberg commented 1 year ago

@svenseeberg Any chance you can try with the latest beta (V2) and see if the issue still persist?

Sure. I installed the Beta App from F-Droid. It seems the issue persists. The Nginx access log shows a 401 (unauthorized) for all requests to /api/v4/users/USERID/image?_=TIMESTAMP for my device.

The Mattermost log prints the following message:

{"timestamp":"2023-01-18 14:13:40.505 +01:00","level":"debug","msg":"Invalid or expired session, please login again.","caller":"web/context.go:113","path":"/api/v4/users/USERID/image","request_id":"61w3o6j5o7bozm5i688buc34mo","ip_addr":"MYIPv6","user_id":"","method":"GET","err_where":"","http_code":401,"error":": Invalid or expired session, please login again., UserRequired"}

If necessary, I can fire up mitmproxy again to capture the Authorization headers and compare with the web app.

Just a general note: I'm using the web app as a workaround. The issue does not exist there.

larkox commented 1 year ago

@svenseeberg Is it possible to try with the official android version? I understand the reasons to use F-Droid, but it is not officially maintained by us (it is maintained by the community), and I want to discard any potential difference between the two before digging deeper into the issue.

If testing with the official android version, let me know, and I will see what we can do :smiley:

svenseeberg commented 1 year ago

If testing with the official android version, let me know, and I will see what we can do smiley

I now installed the current Beta release (2.0.0) from Google Play store. It also does not display the user icons.

I find it interesting that there must be one of 2 things happening: either the app sends different headers for the images requests, or the server does handle the headers differently for the image endpoint?

larkox commented 1 year ago

Created a ticket: https://mattermost.atlassian.net/browse/MM-49779

larkox commented 1 year ago

@svenseeberg Is this still happening?

svenseeberg commented 1 year ago

@svenseeberg Is this still happening?

Which versions should I test? :)

larkox commented 1 year ago

Latest from the store, preferably beta.

larkox commented 1 year ago

Also, if you could share the logs of the app it would be great (Profile -> Settings -> Report a Problem). You can share them with me privately by DM on our community server: https://community.mattermost.com/private-core/messages/@daniel.espino-garcia

Or if you don't feel comfortable for any reason sharing the logs with me, it would be great at least if you could take a look to the logs to see if there is any relevant error on them.

svenseeberg commented 1 year ago

I was searching for the Profile button for quite a long time. Until I realized that there is a curiously dark spot next to bookmarks :joy:

image

I'll strip the log of any personal information, then it should be okay to post here. I emptied the app cache and connected to the server. The resulting logs:

Current User Id: nxcysbxn6fbo3bfxppotzgocia
Current Team Id: XXX
Server Version: 7.10.3 (Build 7.10.3)
App Version: 2.5.1 (Build 6000476)
App Platform: android
Device Model: msm8998
2023/06/29 18:04:06.275 INFO  Running "Onboarding
2023/06/29 18:04:08.884 INFO  Running "Server
2023/06/29 18:04:34.311 INFO  Running "Login
2023/06/29 18:04:35.568 INFO  Running "SSO
2023/06/29 18:05:42.021 INFO  websocket connecting to wss://chat.example.com/api/v4/websocket?connection_id=&sequence_number=0
2023/06/29 18:05:42.135 INFO  websocket connected to wss://chat.example.com/api/v4/websocket?connection_id=&sequence_number=0
2023/06/29 18:05:42.140 INFO  wss://chat.example.com/api/v4/websocket?connection_id=&sequence_number=0 got connection id  4mk6i6ugypynidbc5otadmxafr
2023/06/29 18:05:43.168 INFO  WEBSOCKET RECONNECT MODELS BATCHING TOOK 160ms
2023/06/29 18:05:43.899 INFO  Running "Home
2023/06/29 18:05:56.606 INFO  VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc. {
  "contentLength": 2760,
  "prevDt": 1006,
  "dt": 3682
}
2023/06/29 18:05:56.609 INFO  VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc. {
  "contentLength": 3652.1904296875,
  "prevDt": 1006,
  "dt": 3682
}
2023/06/29 18:06:01.143 INFO  channel switch to john.doe decacafe1234567890ABCDEF00 161.0 ms
2023/06/29 18:06:01.197 INFO  Running "Channel
2023/06/29 18:06:09.014 INFO  Running "Settings

The user john.doe is supposed to have a profile picture, but I only see a black circle. Also, I do have a profile image myself.

If necessary, I can fire up mitmproxy again to capture the Authorization headers and compare with the web app.

I just want to point to that offer again, if you think it helps in any way :)

larkox commented 1 year ago

@svenseeberg Sadly nothing relevant seems to appear on the logs :( .

If necessary, I can fire up mitmproxy again to capture the Authorization headers and compare with the web app.

Seeing the traffic would help a lot, yes. Mainly to make sure the proper calls are being made, and they properly resolve. If you are willing to do it, please let us know the results. Thank you!

svenseeberg commented 1 year ago

I captured the traffic with tcpdump and made screenshots of the HTTP requests with Wireshark. The result is a bit surprising, to be honst. But this also confirms https://github.com/mattermost/mattermost-mobile/issues/4486#issuecomment-650504735 . The cookie is totally missing in the request of the mobile app. That explains the HTTP 401 return code.

image image

Other requests of the Mattermost Mobile app to non-image API endpoints contain an authorization: BEARER ... header.

larkox commented 1 year ago

@enahum Is this something you can take a look at?

enahum commented 1 year ago

and no Authorization header either ?

svenseeberg commented 1 year ago

and no Authorization header either ?

The screenshot contains all information/headers that were sent along with the request. No Authorization header was sent for image endpoints. Other API endpoints do get the Authorization header. Writing and reading messages works w/o problems.

I'll look into the Nginx config again to see if there is some setting that would strip the header for some requests.

enahum commented 1 year ago

is this android, ios or both?

can you describe you auth method?

svenseeberg commented 1 year ago

is this android, ios or both?

I can only confirm Android right now. No idea if iOS is affected. I will try to find a user that has an iPhone at hand.

can you describe you auth method?

Gitlab which actually is a Gitea with some Nginx additional rules to support the expected endpoints. I can do a tcpdump of the login process as well, if it helps.

svenseeberg commented 1 year ago

is this android, ios or both?

Found an iPhone user: seems to work on iPhones.

TheJonny commented 1 year ago

The problem also exists on Android with the F-Droid app or without google services:

The reason is, that the MMAUTHTOKEN cookie is only set (echoed) in the request to /api/v4/users/sessions/device, see

https://github.com/mattermost/mattermost/blob/b7b08dbc0f9b13feee12e7289eae1e3fca0aa682/server/channels/api4/user.go#L2249 ,

which is only made if there is a device token, see

https://github.com/mattermost/mattermost-mobile/blob/f24642989b89d9a1c83ec13aff7d4801715c7131/app/actions/remote/entry/common.ts#L363

amyblais commented 1 year ago

Closing as a Help Wanted issue was opened for this https://github.com/mattermost/mattermost/issues/25353.

TheJonny commented 1 year ago

for certain definitions of "completed"... :)