linagora / tmail-flutter

A multi-platform (Flutter) application for reading your emails, with your favorite devices, using the JMAP protocol!
GNU Affero General Public License v3.0
324 stars 73 forks source link

[EPIC] OIDC #472

Closed hoangdat closed 1 year ago

hoangdat commented 2 years ago

All the stories and technical tasks related to OIDC

hoangdat commented 2 years ago

Hi @chibenwa and @Arsnael, can you share with us the well-know endpoint we can work with OIDC.

chibenwa commented 2 years ago

URL of OIDC config: https://auth.upn.integration-open-paas.org/auth/realms/upn/.well-known/openid-configuration

This can be discovered by calling Webfinger well known endoint.

A fix for webfinger is on its way: https://github.com/linagora/tmail-backend/pull/395

We will tell you when it is ready.

chibenwa commented 2 years ago

Sorry this was a bit long.

Base URL: https://gateway.upn.integration-open-paas.org/oidc

curl call for discovering OIDC endpoints:

curl -XGET  "https://gateway.upn.integration-open-paas.org/oidc/.well-known/webfinger?resource=https://gateway.upn.integration-open-paas.org&rel=http://openid.net/specs/connect/1.0/issuer" -H "Accept: application/json; jmapVersion=rfc-8621"

-> If it returns an error then fallback to basic auth -> else authenticate

Then curl call to get the JMAP session:

curl -XGET  "https://gateway.upn.integration-open-paas.org/oidc/.well-known/jmap" -H "Accept: application/json; jmapVersion=rfc-8621"
hoangdat commented 2 years ago

@chibenwa we use Keycloak provider for OIDC, am I right?

hoangdat commented 2 years ago

Propose for implementation:

or:

chibenwa commented 2 years ago

for web: https://pub.dev/packages/keycloak_flutter

Careful, we might not want to blindly hard-code the keycloak choice... We have a standard here (OIDC) and we likely should stick to it, in order to increase inter-operability.

The implementation, keycloack, is an implementation detail and we should likely be able to handle any technology speaking the OIDC standard.

Cc @atan-linagora

tanandy commented 2 years ago

indeed, AppAuth is a good choice for interoperability. forget about keycloak

dab246 commented 2 years ago

@chibenwa @hoangdat

I try to get session by token but no success. Specifically, I do the following:

  1. After user authentication on https://auth.upn.integration-open-paas.org/auth/realms/oidc I got token
  2. I use the obtained token to get session

Request

URL: https://gateway.upn.integration-open-paas.org/.well-known/jmap
HEADER:
Accept: application/json; jmapVersion=rfc-8621
Authorization: Bearer {{token}}
METHOD: GET

Response

{
     "type": "about:blank",
     "status": 401,
     "detail": "Failed Jwt verification"
}
chibenwa commented 2 years ago

@dab246 can you set up a debugging session with @Arsnael ?

hoangdat commented 2 years ago

@dab246 IMO you are wrong in the auth server and the resource server. Auth console for https://gateway.upn.integration-open-paas.org/.well-known/jmap in https://auth.upn.integration-open-paas.org/auth/admin/master/console/#/. Am I right? @chibenwa

chibenwa commented 2 years ago

Yes James uses a different OIDC server than OpenPaaS.

hoangdat commented 2 years ago

Hi @dab246 please config the app to work with https://auth.upn.integration-open-paas.org/auth/admin/master/console/#/ and https://gateway.upn.integration-open-paas.org/.well-known/jmap.

dab246 commented 2 years ago

@hoangdat I tried but still get the above error

tanandy commented 2 years ago

Yes James uses a different OIDC server than OpenPaaS.

Interesting, What is the OIDC server you are using now ? are you mentionning instead that OpenPaas doesnt user API GTW yet (like krakend) ? or you have keycloak+krakend somewhere else ?

chibenwa commented 2 years ago

Keykloack cas federation used is OpenPaaS setup bringed in limitations. SLO don't work at all on that set up.

Its not a setup we would target in the future so we installed a keycloack for testing keycloack + oidc for james.

Btw we reach some krakend limitations (websockets) so we might reconsider our oidc implementation strayegy.

hoangdat commented 2 years ago

@dab246 @chibenwa I got 400

curl -XGET  "https://gateway.upn.integration-open-paas.org/oidc/.well-known/webfinger?resource=https://gateway.upn.integration-open-paas.org&rel=http://openid.net/specs/connect/1.0/issuer" -H "Accept: application/json; jmapVersion=rfc-8621"
{"type":"about:blank","status":400,"detail":"'rel' supports only 'http://openid.net/specs/connect/1.0/issuer' (URL encoded: http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer)"}%    
chibenwa commented 2 years ago

@Arsnael is currently doing some performance tests,he is doing a run on old 0.5.0 (buggy) but will soon revert to 0.6.0 (not buggy)

Arsnael commented 2 years ago

Back to 0.6.0

hoangdat commented 2 years ago

@chibenwa @hoangdat

I try to get session by token but no success. Specifically, I do the following:

  1. After user authentication on https://auth-dev.upn.integration-open-paas.org/auth/realms/oidc I got token
  2. I use the obtained token to get session

Request

URL: https://gateway.upn.integration-open-paas.org/.well-known/jmap
HEADER:
Accept: application/json; jmapVersion=rfc-8621
Authorization: Bearer {{token}}
METHOD: GET

Response

{
     "type": "about:blank",
     "status": 401,
     "detail": "Failed Jwt verification"
}

hi @chibenwa what user we can use with this keycloak server? Can I add it manually to test?

image
chibenwa commented 2 years ago

hi @chibenwa what user we can use with this keycloak server? Can I add it manually to test?

No please.

Please use the same creds than those for PREPROD

chibenwa commented 2 years ago

@Arsnael can you please tomorrow check the OIDC workflow?

chibenwa commented 2 years ago

Have you tried GET https://gateway.upn.integration-open-paas.org/oidc/.well-known/jmap

(URL input of the user + .well-known/webfinger... to get the OIDC conf then URL input of the user + .well-known/jmap to get the session)

We collocate a OIDC compatible and an OpenPaaS compatible configuration on the same James server hence we have 2 endpoints to differenciate those.

hoangdat commented 2 years ago

Have you tried GET https://gateway.upn.integration-open-paas.org/oidc/.well-known/jmap

oh, it is okie. So, the base URL must be: https://gateway.upn.integration-open-paas.org/oidc? It seems complicated to user when set up the server. Do we have more simple way?

hoangdat commented 2 years ago

all other JMAP request must be in : https://gateway.upn.integration-open-paas.org/oidc/jmap?

hoangdat commented 2 years ago

btw, with OIDC, do we have any way to get current user?

image
hoangdat commented 2 years ago

Sorry this was a bit long.

Base URL: https://gateway.upn.integration-open-paas.org/oidc

curl call for discovering OIDC endpoints:

curl -XGET  "https://gateway.upn.integration-open-paas.org/oidc/.well-known/webfinger?resource=https://gateway.upn.integration-open-paas.org&rel=http://openid.net/specs/connect/1.0/issuer" -H "Accept: application/json; jmapVersion=rfc-8621"

-> If it returns an error then fallback to basic auth -> else authenticate

Then curl call to get the JMAP session:

curl -XGET  "https://gateway.upn.integration-open-paas.org/oidc/.well-known/jmap" -H "Accept: application/json; jmapVersion=rfc-8621"

I need to simplify that:

  1. User need to input what URL?

  2. With the only information: base URL, how we can request to webfinger? What is parameters?

  3. Please explain me about the object

    {
    "subject": "https://gateway.upn.integration-open-paas.org",
    "links": [
        {
            "rel": "http://openid.net/specs/connect/1.0/issuer",
            "href": "https://auth-dev.upn.integration-open-paas.org/auth/realms/oidc"
        }
    ]
    }

    We get href and execute OIDC with it?

  4. After get token? How we connect to JMAP server?

chibenwa commented 2 years ago

1./ When you login on mobile, you need to tell where your JMAP server is.

On WEB this base URL is provided by the static assets.

resource = baseUrl?

Yes

rel = http://openid.net/specs/connect/1.0/issuer? Is it fixed

Yes

3.

We get href and execute OIDC with it?

GET $BASE_URL/.well-known/jmap here with base URL = https://gateway.upn.integration-open-paas.org/oidc so this is GET https://gateway.upn.integration-open-paas.org/oidc/.well-known/jmap

oh, it is okie. So, the base URL must be: https://gateway.upn.integration-open-paas.org/oidc? It seems complicated to user when set up the server. Do we have more simple way?

The /oidc stuff is a deployment detail here (preprod collocates an OpenPaaS deployment and an OIDC deployment). This will not be the case for a real world deployment. No problem!

chibenwa commented 2 years ago

btw, with OIDC, do we have any way to get current user?

I do not understand

hoangdat commented 2 years ago

As current status, we always show the current account like this

image

But right now, in the case of OIDC, how about we get current user info via OIDC endpoint?

chibenwa commented 2 years ago

But right now, in the case of OIDC, how about we get current user info via OIDC endpoint?

You need to get the OIDC endpoint configuration: https://auth-dev.upn.integration-open-paas.org/auth/realms/oidc/.well-known/openid-configuration (Append .well-known/openid-configuration to the endpoint return by webfinger)

Then it gives you the userinfo endpoint: https://auth-dev.upn.integration-open-paas.org/auth/realms/oidc/protocol/openid-connect/userinfo


Alternative: get the name from the session: https://github.com/apache/james-project/blob/b145cdc8c040280cd379fd514804fdd41ae3f918/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala#L158

Account name. Easy. No beahviour divergence between basic auth and OIDC ;-)

That will lead to cleaner code on your side ;-)

hoangdat commented 2 years ago

Discussion on the preprod env:

Context:

  1. Web version:
image
{"type":"about:blank","status":401,"detail":"Failed Jwt verification"}

My understanding

What I need if my understanding is correct

Arsnael commented 2 years ago

My understanding

* `https://jmap.upn.integration-open-paas.org` is not supported to work with OIDC

* only: `https://gateway.upn.integration-open-paas.org/oidc` can work with `token` from OIDC

Correct. Because james does not deal with OIDC directly on the jmap endpoint, we delegated that to the api gateway (made our implem easier and faster). The api gateway is the https://gateway.upn.integration-open-paas.org one. You can access through it:

What I need if my understanding is correct

* please return 404 or any error when I request to
https://jmap.upn.integration-open-paas.org/.well-known/webfinger?resource=https://jmap.upn.integration-open-paas.org&rel=http://openid.net/specs/connect/1.0/issuer

No not that easy. We only have one endpoint for webfinger in James. James has no notion of the api gateway. If I disable it in James, it will be disable for any url you use (as James just say hey I can serve oidc... the rest is not its problem I think)

The trick is with our api gateway. If you point your app to :

So in fact should not use https://jmap.upn.integration-open-paas.org at all. I know it maybe sounds confusing but actually that route should not even be exposed anymore. Just we still had it for perf tests. But now that we have an other env for that we might just stop to expose it when we have time.

Just use the gateway url from now on please and it should work as you expect I believe :)

Regarding tmail-web I know we need to make the change as we manage the helm chart on k8s.

Do you want your tmail-web to point to oidc or normal login for now?

hoangdat commented 2 years ago

Do you want your tmail-web to point to oidc or normal login for now?

Please re-deployed the tmail-web(preprod) with OIDC. Our developers have the way to bypass it with BasicAuth.

Arsnael commented 2 years ago

Done.

However I spotted an other issue that might be related to some recent changes... a 500 from GET https://gateway.upn.integration-open-paas.org/oidc/.well-known/jmap will investigate (something blocking in the reactive pipeline...)

hoangdat commented 2 years ago

no problem when I assign this https://github.com/linagora/tmail-flutter/issues/671 to you?

chibenwa commented 1 year ago

Is this done, @hoangdat ?