Skip to content
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

KEYCLOAK-12137 OpenID Connect Client Initiated Backchannel Authentication (CIBA) #105

Merged
merged 13 commits into from
Jul 29, 2020

Conversation

tnorimat
Copy link
Contributor

@pedroigor
Copy link
Contributor

pedroigor commented May 22, 2020

@tnorimat this is a great start.

Spec-wise, I think it is OK as an initial implementation. We can add more later. I'm also wondering if we should focus on what FAPI profile for CIBA recommends instead of only consider the main spec.

Impl-wise, my main concern is around the cache layer. The same concern I had when reviewing device grant.


### AuthN/AuthZ User Resolver

This provider converts user information in "login_hint", "login_hint_token" and "id_token_hint" to User Model.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that only login_hint is supported by this document? But I guess you just mentioned it here because the resolver could later be used to convert any other form of login hint parameter.

Accordingly to FAPI Ciba Profile there are a few considerations when using login_hint. Are we going to initially provide simple resolution methods for values such as phone, username, email, etc?

How we are going to handle unsolicited authentication requests if we use a "public" known value as a login_hint (e.g.: e-mail)?

Considering that clients need to authenticate maybe we could just trust clients. Mainly when clients are not created through dynamic client registration.

I'm also wondering if the resolver will also be able to resolve user_code too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for the way of identifying the end user to be authenticated by AD, I'd like to support login_hint and id_token_hint as I've commented later on.

As for the contents of login_hint, as you pointed out, it is not appropriate to use "public" known value like phone number, user name and email. IMO it is appropriate to use the value known only by the client and keycloak. However, I think such the value is case-by-case so that keycloak itself cannot implement actual resolver. As a compromise, keycloak implement resolvers for username and email but mention on the document that these resolver should only be used for test-use, not be used in service. WDYT?

As for clients that can be allowed to use CIBA flow, we can control which client be allowed to use CIBA flow using Client Policies . I'd like to add this description about it on this PR's design document. WDYT?

As for user_code, I agree with you. I'd like to add to this PR's design documentation that the resolver for user_code is also supported. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we should advertize the risks when using public known values. The id_token_hint seems more natural for me but it would require the client to keep the id_token for a user and I'm not sure if all clients using CIBA would be able to authenticate their users beforehand in order to get the token. I understand that the different paths for identifying users are stricly related on the use-case and how the client can pass the information to the OP?

I also think that the user code is useful so users can provide their user codes during registration or through the account console (or even by setting this from your "management" system through our APIs) so that when resolving the user code we match it based on some user attribute (which can potentially be set on a per-realm or per-client basis).

What about login_hint_token? Could we use it to communicate values that are encrypted or signed? It looks like a good option too.

I'm not sure about Client Profiles. It is more related to enforcing policies instead of enabling or disabling features?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option can be that Keycloak can implement resolver, which will be able to somehow encrypt the userID with the client secret. So for example the flow can be like this:

  • Client will "encrypt" the userID (or username/email) with the clientSecret and send it to the Keycloak in "login_hint"
  • Keycloak will "decrypt" the userId with the clientSecret, which is known just to the Keycloak server and client.

The encryption will mean to use some specified algorithm (EG. Aes-128?), which can be selected in the configuration of the provider somehow.

I don't know if this makes sense or not and I am not aware of all the standards behind this. Just an idea :)

Copy link
Contributor Author

@tnorimat tnorimat Jun 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroigor

I'm not sure about Client Profiles. It is more related to enforcing policies instead of enabling or disabling features?

Yes, but this Client Policies' design document is in under discussion.

Copy link
Contributor Author

@tnorimat tnorimat Jun 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, there is 2 types of representation for conveying user to be authenticated from a client (CD) to keycloak :

  • public or guessable
    can be acquired from public sources (e.g. name, phone number)
    even if cannot be acquired from public sources, easy to guess (e.g. email address)
  • not public and not guessable
    cannot be acquired from public source and hard to guess (e.g. UserModel's ID in keycloak internal)

Considering security, we pay attention to the following points :

  • Unsolicited backchannel authentication request by a malicious user (impersonation)

    • public or guessable user information is vulnerable to this attack.
    • Regardless of the way of conveying user to be authenticated, User Code seems to be effective countermeasure.
  • Unsolicited backchannel authentication request by a malicious other client to attack other victim client (replay, forge legitimate backchannel authentication request)

    • PPID seems to be effective countermeasure.
    • Encryption seems to be effective countermeasure.
    • Signed JWT seems to be effective countermeasure.
    • Regardless of the way of conveying user to be authenticated, User Code seems to be effective countermeasure.
  • Unsolicited backchannel authentication request by a malicious client itself (keep user's user_code and other authentication related information once this client tried CIBA flow with this user, forge legitimate backchannel authentication request)

    • No principle effective countermeasure by keycloak seems not to exist (but might be my misunderstanding). Using binding message and the end user being taking extra precaution on it seems to be only the way to prevent it.
  • PII leakage on the wire

    • PPID seems to be effective countermeasure.
    • Encryption seems to be effective countermeasure.

Considering these points, my proposal is as follows :

  • user_code

    • supported
  • login_hint

    • supported
    • Resolver : keycloak provides the resolver for the following information
      • User Information
        • username
        • email
    • Encryption : this resolver support encryption for them by using client secret with AES128/192/256bit
  • login_hint_token

    • supported
    • Resolver : keycloak provides the resolver for the following token
      • Format : JWT
      • Profile : TBD but now considering SET
      • User Information
        • username
        • email
    • Integrity Protection/Message Authentication : JWS
    • Encryption : JWE
  • id_token_hint

    • supported
    • PPID support for "sub"
  • request (signed authentication request)

    • supported

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also @pedroigor pointed out, there is the case that the user registers multiple ADs. Therefore, the client needs to specify which AD is used for user authentication. CIBA specification seems not to mention it so that we need to specify it as keycloak specific way. If we treat only single AD per user, we does not need consider this issue. Should we support only support single AD or multiple ADs? If supporting multiple ADs, should we support it as a follow-up other PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tnorimat +1 to your proposal. Regarding support for multiple ADs, I vote to do it as a follow-up if possible.

In general, it will be good to divide this work into bigger amount of smaller pull requests (due the easier review etc), instead of adding one super-big PR :-) Of course, there can be always exceptions to this rule (For example if there will be additional issues with the migration in case that initial PR and follow-up PR will be done in different Keycloak releases etc).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mposolda I see, I'd like to divide this work into several pull requests and JIRA tickets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mposolda As for support for multiple ADs, I agree with you. I'd like to realize it as a follow-up task.

design/client-initiated-backchannel-authentication-flow.md Outdated Show resolved Hide resolved
- Request Parameters
* login_hint : supported
* login_hint_token : NOT supported
* id_token_hint : NOT supported
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not the id_token_hint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To identify the user to be authenticated by AD, it is sufficient that at least one of these options be supported. I thought login_hint is the simplest option so that I decided to support only login_hint option.

But re-considering this matter, it is not so much difficult to support id_token_hint because the current keycloak has already supported id_token_hint defined in OIDC.

Therefore, I'd like to support login_hint and id_login_hint . WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unresolving just because it seems that this section of the design is not yet up-to-date with what you guys discussed in the other part related to "AuthN/AuthZ User Resolver"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mposolda Could you please refer to the review comments for "AuthN/AuthZ User Resolver" about login_hint, login_hint_token and id_token_hint support?


(2) : keycloak returns to CD Backchannel Auth Response. It includes "auth_req_id" defined in CIBA protocol specification to identify the CIBA flow invoked by the request (1).

(3) : Backchannel Auth Req/Res part pushes Backchannel Auth Request related context data bound with "auth_req_id" onto Auth Req Context Cache in order for Token Req/Res part to restore it for generating tokens afterwards.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a new cache? There are some discussions going on about Device Grant and I think we can leverage authentication sessions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to study the way without a new cache and refer to Device Grant's discussion. Therefore, let me give some time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I really think that touching our cache layer is always critical. It is already an area that we suffer in terms of configuration and management. If we can just leverage the caches we have that would be fantastic. In fact, if we are going to need a separate cache for this and any other flow we want to support, things will become complicated. Maybe this shows a limitation on our cache layer. But yeah, I think we can leverage authentication sessions. As I said, I did some experiments on top of the changes to the device grant and it seems to work fine. I just did not implement the pooling stuff, but the device flow itself works just fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one limitation to the authenticationSession cache, that it is not cross-dc aware. Which can be possibly issue with the absence of sticky sessions? I am not CIBA expert, but I guess sticky sessions is not something, which can be relied on due the fact that everything is backchannel in CIBA?

I mentioned another idea in the comment above whether "auth_req_id" can be the JWE. This will allow that we won't need to store it anywhere on the Keycloak server side.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroigor @mposolda As for "auth_req_id" and the cache, I've written my proposal in the discussion just above so that could you please refer to it?


3 can partially satisfies CIBA protocol specification but no traffic is exchanged among nodes in the cluster due to this token request throttling. However, it seems that keycloak does not prepare such collection so that implementing it or introducing some kind of OSS is required.

In this time, 2 is to be realized.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the spec could allow issuing the auth_req_id every time the client tries to pool tokens from the server we could easily solve this problem. Or even if we could require clients to send an additional parameter for the same purpose so that we know when the last auth_req_id was issued and if the time it is being sent is within the expected interval.

I also think #2 is the best way to go (not yet ideal). Although I know how bad the operation can warm a cluster depending on the number of updates.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. At this time, I'll try #2 but considering the performance problem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is a tricky one. I was thinking though ... Why do we need to worry about replicating state across nodes in a cluster but just let each node track auth_req_id independently ?

It would be the best effort and a malicious client wouldn't be able to damage the system so badly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for each node tracking the system independently. Which AFAIK is the solution number 3.

This is good compromise among security and performance IMO. And there is no need to introduce any new infinispan cache into standalone-*.xml file just because that as local cache can be easily created programaticaly. I can imagine something similar to how we create "Revision" caches programatically in the DefaultInfinispanConnectionProviderFactory.initContainerManaged() method.

I've did some small prototype based on the "putIfAbsent" where each item adds the item to the cache with the expiration of interval (5 seconds). The unsuccessful "putIfAbsent" call means that there is already item for this "Auth_req_id" and hence client was too fast with sending request and he should be rejected. The prototype is here: mposolda/keycloak@9918e86

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroigor @mposolda
Yes, I agree with you. I'll revise this PR's design document to employ the number 3 method. I'll study how to realize it by studying @mposolda 's prototype.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tnorimat Cool, Thanks!

2. Executes all the processes that need to be executed after the end-user logged-in like creating User Session and Authenticated Client Session that are needed to generate tokens in Token Req/Res part.
3. Informing Token Req/Res part of 1's result.

1 is highly dependent on actual use-cases while 2 and 3 seems to be use-case independent. Therefore, The abstract base class implementing 2 and 3 is provided and the class extending this abstract base class is also provided.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would #1 be an SPI?

Can we use security event tokens for this communication?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, #1 would be an SPI.

Is "security event tokens" you mentioned RFC 8417 Security Event Token (SET) ? I've not yet read it so that I'd like to investigate into it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is the spec. In fact, we should have been using this for other types of events we use (adapter, logout, etc).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I would like to use Security Event Token(SET). AFAIK, the current keycloak does not yet support SET so that we need to support it at first before implementing CIBA. Is that correct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a suggestion. We don't necessarily need to consider everything in the spec but provide some standard format for the events we send to and get from AD.

If you think it is too much, that is fine. But it would be much better than come up with our own format.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroigor Thanks. I'd like to decide whether SET is used as the formal JWT profile or not. But it is beneficial for us to implement SET because it can be used not only CIBA but also pushing logout security events to RPs as you mentioned.


### Settings

To configure inside CIBA part's operation, CIBA policy is introduced as part of Admin Console's Realm Settings.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about having this as a realm setting.

  1. Clients may have different needs. Although we only support poll, later we may support other modes.
  2. expires_in is OK as a default for all clients within a realm. But later we may want to also allow clients to send this.
  3. Clients may have different requirements for interval.

In addition to that, how we enable CIBA for a client ? Do we want a switch similar to what we have for Direct Grant ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I'd like to enable the settings per client but also support per realm as default setting (setting per client supersede the one per realm). WDYT?

As commented earlier, we can control which client be allowed to use CIBA flow using Client Policies . I'd like to add this description about it on this PR's design document. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me to have a default realm setting. It should be easier to configure if all your clients share the same configuration (we don't have the concept of client templates anymore).

As I mentioned before, not sure about client policies for such a thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Therefore, I'll revise this PR's design document to write about this settings (setting per client supersede the one per realm).

For example, by using Client Policies, keycloak can accept the bachchannel authentication request sent from the clients whose client roles include "ciba-flow-allowed" and refuse it from the clients whose client roles does not include "ciba-flow-allowed".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

+--------------------------------+ +-----------+
```

(i) : keycloak sends to Decoupled Auth Server an AuthN/AuthZ by AD request with "Decoupled Auth ID" bound with "Auth Result ID" bound with "auth_req_id" issued to CD.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear for me yet why we need the Decoupled Auth ID. I have an idea, but maybe you can provide more details (not expose auth_req_id, for instance)

Also, don't you also want to send the binding_message so that the AD can show that information when obtaining the authorization from the user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for Decoupled Auth ID, I plan that it is version 4 UUID String and keycloak internally maps it to corresponding auth_req_id so that auth_req_id itself is not exposed to Decoupled Auth Server. If you have a good idea, I would be happy if you tell me.

As for binding_message, yes I agree with you. I will describe the interface the same as "Interface between Inside and Outside CIBA Protocol" section.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. That is what I was suspecting in regards to having the decoupled auth id.

But how bad is it to communicate the auth_req_id itself if this data is transmitted over a secure protocol? Which I think is a MUST ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as you said and considering the followings point, I would like to use auth_req_id instead of Decoupled Auth ID :

  • keycloak and Decoupled Auth Server are under the control by the same adnimistrator (but keycloak cannot check it. keycloak's user themselvles confirms it)

  • communcation between keycloak and Decoupled Auth Server must be over TLS

  • auth_req_id is bound with CD so that Decoupled Auth Server cannot receive tokens in return for auth_req_id

WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me it makes sense. Even if the decoupled server is not within the same domain, he can't do much about it. And in the worst case, we can allow passing the Decoupled Auth ID as you initially proposed. Which would be just an opaque reference to the auth_req_id.

@stianst stianst requested a review from hmlnarik May 25, 2020 10:48
@stianst
Copy link
Contributor

stianst commented May 25, 2020

@hmlnarik FIY you may want to take a quick look at this especially if it introduces a new cache

@tnorimat
Copy link
Contributor Author

@pedroigor Yes, I plan to support FAPI CIBA Profile as the final goal. At first, I'd like to support CIBA by this PR's design document. After realizing CIBA following this PR's design document, I'd like to support FAPI CIBA Profile by updating this PR's design document. WDYT?

@pedroigor
Copy link
Contributor

pedroigor commented May 27, 2020

@tnorimat IMO, we should look for FAPI-based implementations because they usually provide a more secure profile on top of the specifications.

And we also keep our roadmap more aligned to our Open Banking initiatives (which you guys are contributing a lot !).

Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tnorimat Thanks for the specs! I've added few inline comments, especially in regards to caches. I am not CIBA expert, so not sure if everything I proposed makes sense. Just some ideas :) CC @pedroigor


### AuthN/AuthZ User Resolver

This provider converts user information in "login_hint", "login_hint_token" and "id_token_hint" to User Model.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option can be that Keycloak can implement resolver, which will be able to somehow encrypt the userID with the client secret. So for example the flow can be like this:

  • Client will "encrypt" the userID (or username/email) with the clientSecret and send it to the Keycloak in "login_hint"
  • Keycloak will "decrypt" the userId with the clientSecret, which is known just to the Keycloak server and client.

The encryption will mean to use some specified algorithm (EG. Aes-128?), which can be selected in the configuration of the provider somehow.

I don't know if this makes sense or not and I am not aware of all the standards behind this. Just an idea :)

- Request Parameters
* login_hint : supported
* login_hint_token : NOT supported
* id_token_hint : NOT supported
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unresolving just because it seems that this section of the design is not yet up-to-date with what you guys discussed in the other part related to "AuthN/AuthZ User Resolver"


## Design and Implementation

This section describes how to realize what Specification section determined.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have few points regarding this part, especially with the respect to caches. Few things:

a) We have CodeToTokenStoreProvider, which provides some ability to "single-use" behaviour and it is cluster/cross-dc aware. It is used for exchange OIDC "code" and ensure that "code" is single-use as mentioned in the OIDC specification. This one can be possibly used by the step 8 from the picture to ensure that only single tokenRequest will be able to retrieve "Auth Result ID" and send the successful Token response.

BTV. Since CodeToTokenStoreProvider can be used to solve similar use-case like the "Auth Result" cache, I suggest to maybe refactor CodeToTokenStoreProvider and make it a bit more generic. It can be even possible to "merge" it with the existing SingleUseTokenStoreProvider as mentioned in the javadoc of the SingleUseTokenStoreProvider.

b) Can the "auth_req_id" be a JWE encrypted by the realm AES key? This means that it will be opaque string to the client and just Keycloak server will be able to "decrypt" it when it later receive it in the TokenRequest (step 6 from the picture). Keycloak server will be able to load some useful informations like "Auth Result ID"

So regarding the first 2 points, I can imagine the flow like this:

  • Client sends the Backchannel Auth Request. Keycloak generates the "Auth Result ID" and adds it to the JWE together with some other useful info (userId, clientId etc) and make the "auth_req_id" from it.

  • In step 3, there is possibly no need to save "auth_req_id" anywhere. The "Auth Req Context Cache" maybe won't be needed at all?

  • The AuthResultId will be passed to the "Outside CIBA flow" as mentioned in the picture

  • In the step 5 from picture, the "Auth Result ID" will be passed to the "Auth Result Cache", which will be defacto existing infinispan actionTokens cache. It will use CodeToTokenStoreProvider for that (eventually renamed to the more generic provider as mentioned above)

  • In the step 6 from picture, the client sent "auth_req_id" to the Keycloak server. Keycloak server will first do the "throttling" check as we discussed in the other comment to prevent DoS.

  • Once "throttling" check passed, Keycloak will be able to decrypt "auth_req_id" JWE and obtain "Auth Result ID" from it. Also other context info like scopes etc. It can then call method "CodeToTokenStoreProvider.remove" for the particular "Auth Result ID" . The semantics of CodeToTokenStoreProvider.remove ensures that only one call to this can success. So there should be only one successful TokenResponse sent to the client. T

WDYT?

Copy link
Contributor

@pedroigor pedroigor May 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the auth_req_id works as a code. I think this approach fits. That is a good catch.

In regards to its value, if I read the specs correctly it is opaque and we can have whatever we want.

I'm not sure though if we need to encrypt the JWT or just have it signed. One thing is for sure, a JWT as an auth_req_id help us to store/share data with the client/server. But this "token" is really something known by the client where all the transmission should be secure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In regards to the login hint resolver, that is something I was thinking too when I did this comment #105 (comment).

So we could use the login_hint_token for this. If I read the spec correctly, it is all about having some agreement about how this token will look like.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also not sure if "auth_req_id" needs to be JWE or signed JWT. The "auth_req_id" will contain the AuthResultID in it, this is probably fine to expose to the client?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroigor @mposolda Considering this discussion, what do you think about the following?

  1. When a backchannel authentication arrives, keycloak generates Auth Result ID and also generate auth_req_id which includes parameters that are held by the cache Auth Req Context Cache I've initially proposed.

  2. auth_req_id is signed and encrypted by JWS/JWE, which make unnecessary Auth Req Context Cache I've initially proposed.

  3. Auth Result Cache can be realized by the existing actionToken cache via the provider refactoring CodeToTokenStoreProvider. Auth Result Cache is for single-use, but considering the following case that the CD(client) requests tokens before the completion of authentication by AD so that keycloak only removes this cache entry after the completion of authentication by AD.

  4. When Token Request arrives, keycloak at first check whether access throttling is applied or not. If not, keycloak decrypt the auth_req_id, extract the key for accessing the cache entry of Auth Result Cache, get and remove this entry to find out the result of authentication by AD.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 I'm just not sure about the need for encryption but only signing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 . Also +1 to @pedroigor 's comment about encryption VS signing. It seems like a trade-off etween better security (using encryption+signing) and less complexity (using just signing). Encryption is needed just in case that we don't want client to know values of some parameters? Leaving to your judge if this would be an issue or not...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mposolda At this time I'd like to employ JWS. However I'd like to consider JWE as an option. I'm afraid that something need to be secret might arise when I start the implementation.


(2) : keycloak returns to CD Backchannel Auth Response. It includes "auth_req_id" defined in CIBA protocol specification to identify the CIBA flow invoked by the request (1).

(3) : Backchannel Auth Req/Res part pushes Backchannel Auth Request related context data bound with "auth_req_id" onto Auth Req Context Cache in order for Token Req/Res part to restore it for generating tokens afterwards.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one limitation to the authenticationSession cache, that it is not cross-dc aware. Which can be possibly issue with the absence of sticky sessions? I am not CIBA expert, but I guess sticky sessions is not something, which can be relied on due the fact that everything is backchannel in CIBA?

I mentioned another idea in the comment above whether "auth_req_id" can be the JWE. This will allow that we won't need to store it anywhere on the Keycloak server side.


The one way is that keycloak sets "auth_req_id" to User Session's note when generating this User Session and find it afterwards by linear search. It seems to have serious performance problem especially when keycloak having vast number of User Sessions and distributed among several nodes.

The faster way is using its User Session ID as a search key. Therefore, in Backchannel Auth Req/Res part, keycloak issues the User Session ID in advance and use it when generating User Session in AuthN/AuthZ by AD part. However, this way cannot utilize key affinity feature of Infinispan.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to do something like this.

I can imagine that UserSessionID is even the same as "Auth Result ID", but I don't know if it has security implications? As I guess that the "Decoupled Authentication server" should not be able to know the UserSessionID, however he will be able to know "Auth Result ID" ? Another alternative is to use again something like generate userSessionId from the AuthResultID and realm keys. So that it is just Keycloak server, who is able to "Decode" from the userSessionID from 2 inputs (AuthResultID, realm HMAC or AES key).

Copy link
Contributor

@pedroigor pedroigor May 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In regards to authentication sessions vs cross-dc. I thought we don't push too much to our cross-dc support?

You won't need sticky sessions because the auth_req_id already references the session we need to lookup. It is just a matter of having the session shared across nodes. But if cross-dc support is a must, yeah, I think authentication sessions are not an option.

But I was thinking ... Once the user has consented to the client request (at the AD) we are going to create a session, right? Maybe, until that happens we don't need to store anything as everything we need to know is in the auth_req_id. Once the user consented and the user session is created, the decision to whether or not the token request should be fulfilled can be based on a simple query in the "sessions" cache. Makes sense? Is that what you are proposing?

So maybe we don't even need the single-use behavior you mentioned ...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that cross-dc support will be good. IMO the fact that it is "Technology preview" doesn't mean that we can relax on supporting it for some Keycloak features. But maybe I am wrong here.

Per https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.10.1.1 I see this: Once redeemed for a successful token response, the auth_req_id value that was used is no longer valid.

So this probablb means that it is supposed to be single-use?

Copy link
Contributor

@pedroigor pedroigor May 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The single-use behavior I meant is in regards to using the CodeToTokenStore.

We still need the auth_req_id to be single-use, but we can do it like that:

  1. Client sends the authentication request
  2. Server generates an auth_req_id using a JWT format containing some identifier that we can use later to pass to the AD (so we can recognize that a request from AD is related to the client authentication request). This JWT may have some expiration, iat, azp, etc, to make sure we only accept auth_req_id from clients within a period.
  3. The server sends the request to AD to authenticate the user
  4. AD ask user to approve the solicited authentication request. Validates the binding_message if necessary, etc.
  5. Once the user approved the request, AD sends back the auth_req_id
  6. The server creates a user session based on the auth_req_id

Clients pooling the server for a token will send the auth_req_id and once a user session exists and is associated with the auth_req_id, we return the tokens. Otherwise, the server responds with a message whenever the auth_req_id expires and is no longer invalid. If the client tries to use the token again, after a determined period, it won't be possible. When processing the auth_req_id for the first time after user approval, the session will not be tied with the auth_req_id yet, so we know it is the first time the auth_req_id is used.

We don't necessarily need to pass the auth_req_id to the AD. But only some reference that we can associate with the auth_req_id. Some data we put inside the auth_req_id token. But I'm not sure yet how bad is to just pass the auth_req_id to AD, considering the AD would not be able to obtain tokens (the server requires client authentication) and the token would not leak if using a secure protocol.

Copy link
Contributor

@mposolda mposolda May 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clients pooling the server for a token will send the auth_req_id and once a user session exists and is associated with the auth_req_id, we return the tokens. Otherwise, the server responds with a message whenever the auth_req_id expires and is no longer invalid. If the client tries to use the token again, after a determined period, it won't be possible. When processing the auth_req_id for the first time after user approval, the session will not be tied with the auth_req_id yet, so we know it is the first time the auth_req_id is used.

Yes, the CodeToTokenStore provider (or SingleUseTokenStoreProvider) is useful in the cases when you want to guarantee single-use across whole cluster/cross-dc environment. Which is maybe not a strict requirement in the CIBA specification (unlike OIDC "code" parameter where the strict requirement is). If you want to guarantee strict single-use, then you may always end with the scenario like this:
a) Client sends the tokenRequest, which will be processed on Keycloak node1
b) Keycloak node1 will see that userSession is not yet associated with auth_req_id
c) At the same time, client sends the same tokenRequest, which will be processed on Keycloak node2
d) Keycloak node2 will see that userSession is not yet associated with auth_req_id
e) In the meantime request1 will associate the "auth_req_id" with userSession
f) At the same time, concurrent request2 will also associate the "auth_req_id" with userSession
g) both requests will successfully return TokenResponse. Which is bad if we want to strictly guarantee single-use

I don't know if this would be a problem? If not, then we don't need strict single-use and the CodeToTokenStore/SingleUseTokenStoreProvider at all.

The (a) and (c) needed to end of different cluster node, assuming that we will do "throttling", which will guarantee the KEycloak reject concurrent requests from client sent to same cluster node as discussed in other sub-thread :)

We don't necessarily need to pass the auth_req_id to the AD. But only some reference that we can associate with the auth_req_id. Some data we put inside the auth_req_id token. But I'm not sure yet how bad is to just pass the auth_req_id to AD, considering the AD would not be able to obtain tokens (the server requires client authentication) and the token would not leak if using a secure protocol.

Yes, I believe the "Auth Result ID", which @tnorimat proposed in the design is the reference, which can be eventually saved as one of the claims in the "auth_req_id" JWT/JWE? So it looks that we're on same page here. I am also not sure how bad it is if "auth_req_id" is shared with the AD. I assume this is not ideal based on what @tnorimat mentioned.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedroigor You mean the scenario when you have 2 concurrent requests to update same userSession and hence you expect one of them to fail? Yes, there are ways to avoid that. For example there is 3 arguments "cache.replace" method (The item is replaced just if the current value is equal to the new value). However, I recall some issues with that few years ago when worked on cross-dc stuff. So the "guaranteed" way is the single-use cache (and CodeToTokenStoreProvider), which should reliably ensure the single-use. This stuff is used for example for OIDC codes and IMO it works fine and would work fine here as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, something like that. I'm 100% for your proposal to use the CodToTokenStoreProvider. The only concern I have in this regard is that cross-dc usually requires additional steps that might not be necessary when in a single cluster scenario.

So any overhead we add in order to support cross-dc affect people doing single-dc. IMO, we should also try to be as stateless as possible. All that makes a huge difference when deploying and scaling Keycloak, especially when doing single-dc which I think is the majority of use cases?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, even in single-dc you can have the issue with 2 concurrent threads trying to update same entity. And for example, before we added cross-dc support, we had the issue with single-use code, which was not really single use (even in single-dc it could happen that same "code" was used multiple times). Regarding implementation, the "CodeToTokenStoreProvider" or "SingleUseProvider" should guarantee in both single-dc and cross-dc that particular stuff is really single-used, so there is no additional overhead in the "consumer" code.

But of course, in cross-dc environment, there is additional overhead due the network latency etc. So there is always some price to pay for cross-dc support. But people, who want to use cross-dc, should expect this additional price to pay.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mposolda

I can imagine that UserSessionID is even the same as "Auth Result ID", but I don't know if it has security implications? As I guess that the "Decoupled Authentication server" should not be able to know the UserSessionID, however he will be able to know "Auth Result ID" ?

As you suggested before, "Auth Result ID" is retained in actionToken cache by using CodeToTokenStoreProvider or refactored one, I think that UserSessionID can be stored on this cache entry so that we do not need to send UserSessionID to "Decoupled Authentication Server". WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mposolda
Copy link
Contributor

@tnorimat @pedroigor Ah, one last thing: It seems to me that it will be also great to support "long polling" described in the CIBA specification. It seems that Resteasy have some support for "async" requests, so hopefully it will be somehow possible. From the infinispan perspective, it shouldn't be an issue as infinispan has listeners (and hotrod listeners for remote caches used in cross-dc environment), which can notify when particular "Auth Result ID" is added to the cache.

It seems that "long polling" can be more convenient for most of the clients instead of the standard polling, but maybe I am wrong. Support for PING and PUSH modes will be also nice, but that is probably also for the future I guess?

@pedroigor
Copy link
Contributor

@mposolda I also read that part and for me long pooling (by reading the specs) is related blocking requests?

IMO, the discussions around the standard pooling are going fine and that would be our first goal.

For push and ping, I also think it can be done later.

@mposolda
Copy link
Contributor

@mposolda I also read that part and for me long pooling (by reading the specs) is related blocking requests?

IMO, the discussions around the standard pooling are going fine and that would be our first goal.

For push and ping, I also think it can be done later.

+1 for add it later. Just wanted to discuss it :) With long-polling, the client, which send the HTTP request, will be blocked for 30 seconds. But I guess that on Keycloak server side, there won't necessarily be any HTTP thread blocked for 30 seconds if we use some JAXRS Async capabilities? That is what I meant.

@tnorimat
Copy link
Contributor Author

@pedroigor As for OIDC CIBA or FAPI CIBA, I see, I would like to aim at FAPI CIBA on this PR's design document in order to aligh to Open Banking Security Profile. I'll revise this PR's design document. Is it OK?

@pedroigor
Copy link
Contributor

@tnorimat +1

@tnorimat
Copy link
Contributor Author

@pedroigor OK, I'll try to achive FAPI CIBA in this RP. I'll revise this PR's design document encompassing it.

@tnorimat
Copy link
Contributor Author

tnorimat commented Jun 1, 2020

@pedroigor @mposolda As for long polling, I also agree with you. I'll revise this PR's design document to mention that long polling is supported.

As for ping and push mode, I also agree with you. These will be realized in the future.

@mposolda
Copy link
Contributor

mposolda commented Jun 1, 2020

@pedroigor @mposolda As for long polling, I also agree with you. I'll revise this PR's design document to mention that long polling is supported.

@tnorimat Thanks for consider long-polling. However for this one, I am also not sure if it should be implemented now or rather in the separate iteration / separate PR?

The challenge here is, that when client sends the HTTP request, which will be blocked on the server for 30 seconds, then we should ensure that there is not blocked HTTP undertow worker thread for this whole time. Blocking threads will add possibility for DoS attacks and other performance considerations and probably won't be ideal... So to avoid this challenge, I think we may need to look into:

  • JAX-RS asynchronous requests/responses. I believe there is support for this at JAX-RS specification and RestEasy should support it too.
  • Infinispan client notification listeners

I can imagine the flow when HTTP thread will be "suspended" once request arives. And the thread it will be later "awaken" and continue when the condition passed (So either 30 seconds timeout or client listener was notified).

Due those additional challenges, I can imagine this will be done in an additional step to the initial rather than initial implementation. But from the longer-term perspective, it will be very cool to support long-polling IMO.

@tnorimat
Copy link
Contributor Author

tnorimat commented Jun 5, 2020

@mposolda I see, I'd like to support long-polling by a follow-up task because it seems that it takes a lot of time to study this matter. I'd like to review this PR's design document to mention it.

@tnorimat
Copy link
Contributor Author

tnorimat commented Jun 9, 2020

@pedroigor @mposolda I've proposed Decoupled Auth Server as a default Implementation of AuthN/AuthZ by AD part of outside CIBA Protocol. I've re-considered it and found that it might be better to provide another default implementation that keycloak user can use out of the box without preparing anything (such the decoupled auth server). For example, SMS authentication. WDYT?

@mposolda
Copy link
Contributor

mposolda commented Jun 9, 2020

@tnorimat I don't have much to add to your last comment. AFAIK the SMS authentication can be problematic and non-trivial to be easily tested - I don't know if this is dependent on the country and various other inputs... But maybe I am wrong, I don't have too much knowledge in this area.

@pedroigor
Copy link
Contributor

I agree with Marek. It would be awesome to have something OOTB, but from what I've experienced the communication with a broker is usually very specific and hard to come up with a generic solution?

@tnorimat
Copy link
Contributor Author

tnorimat commented Jun 9, 2020

@mposolda @pedroigor Yes, I agree with you. I'd like to work along with the first proposal (Decoupled Auth Server).

@tnorimat
Copy link
Contributor Author

@pedroigor @mposolda I think the disscussion is wrapped up the following points. I'll revise this design documentation to incorprate these points.

  • CIBA Specification
  1. FAPI CIBA : support
  2. How to convey the user info from CD to OP
  3. PPID for "sub" in id_token_hint : support
  4. User Code : support
  5. Signed Authentication Request : support
  6. Token Request Throttling : per node without cache sync
  7. Long Polling : support in the future
  8. ping mode/push mode : support in the future
  9. Multiple ADs per user : support in the future
  • CIBA Implementation
  1. Settings : per realm as default, overridden per client
  2. how to implement auth_req_id : JWS/JWE
  3. how to implement Auth Result ID : refactored CodeToTokenStore + existing actionToken cache
  4. Cross-DC : support
  • Outside CIBA Protocol
  1. Decoupled Auth ID : use auth_req_id
  2. keycloak <-> Decoupled Auth Server : Interface
  3. keycloak <-> Decoupled Auth Server : Message Format

@pedroigor
Copy link
Contributor

@mposolda @tnorimat Once this document is updated to what was discussed so far (if not already), isn't time to start implementing it and reviewing some code :) ?

Really excited about this one and it would also help us with the device grant flow.

@tnorimat
Copy link
Contributor Author

@pedroigor I'm now revising the design document. I've implemented Proof-of-Concept level codes based on the original design document. I'll revise codes based on the revised version of the design document.

@pedroigor
Copy link
Contributor

pedroigor commented Jun 18, 2020

@tnorimat Nice. I'm not rushing :) Please, take your time. But just trying to move this forward considering that the main points are addressed, IMO.

Let me know if you are happy with discussions to get approval from my side.

@tnorimat
Copy link
Contributor Author

I've revised the design document about the following points.

  • CIBA Specification
  1. FAPI CIBA : support
  2. How to convey the user info from CD to OP
  3. PPID for "sub" in id_token_hint : support
  4. User Code : support
  5. Signed Authentication Request : support
  6. Token Request Throttling : per node without cache sync
  7. Long Polling : support in the future
  8. ping mode/push mode : support in the future
  9. Multiple ADs per user : support in the future

I've not yet treated the following points.

  • CIBA Implementation
  1. Settings : per realm as default, overridden per client
  2. how to implement auth_req_id : JWS/JWE
  3. how to implement Auth Result ID : refactored CodeToTokenStore + existing actionToken cache
  4. Cross-DC : support
  • Outside CIBA Protocol
  1. Decoupled Auth ID : use auth_req_id
  2. keycloak <-> Decoupled Auth Server : Interface
  3. keycloak <-> Decoupled Auth Server : Message Format

Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tnorimat Thanks for the update! Added one very minor inline comment inside.

design/client-initiated-backchannel-authentication-flow.md Outdated Show resolved Hide resolved
@tnorimat
Copy link
Contributor Author

tnorimat commented Jul 1, 2020

I've revised the design document about the following points.

  • CIBA Implementation
  1. Settings : per realm as default, overridden per client
  2. how to implement auth_req_id : JWS/JWE
  3. how to implement Auth Result ID : refactored CodeToTokenStore + existing actionToken cache
  4. Cross-DC : support
  • Outside CIBA Protocol
  1. Decoupled Auth ID : use auth_req_id
  2. keycloak <-> Decoupled Auth Server : Interface
  3. keycloak <-> Decoupled Auth Server : Message Format

There is nothing remaining items.

@tnorimat
Copy link
Contributor Author

tnorimat commented Jul 1, 2020

@pedroigor During disucussion, we've concluded that keycloak communicates with Decoupled Auth Server with "auth_req_id". However, I've found that it requires sending "auth_req_id" from Backchannel Auth Req/Res part to AuthN/AuthZ by AD part which duplicates "Auth Result ID" for the same objective of identifying the CIBA flow.

Considering this point, I've revised the design document to send "Auth Result ID" from AuthN/AuthZ by AD part of keycloak to Decoupled Auth Server instead of "auth_req_id".

@VinodAnandan
Copy link

VinodAnandan commented Jul 13, 2020

@stianst @mposolda @pedroigor @hmlnarik Could you please let us know if this needs further reviews?

@pedroigor
Copy link
Contributor

+1 to merge and have an initial implementation (and probably a few last points of discussion)

@tnorimat
Copy link
Contributor Author

@mposolda Is there anything else missing?

Copy link
Contributor

@mposolda mposolda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tnorimat No, I am merging this. Thanks and sorry for late review.

@mposolda mposolda merged commit 47ea1c6 into keycloak:master Jul 29, 2020
@aberthout
Copy link

Hi everybody :)

I'm happy to read this post ! I'm looking for two weeks ago a lot of informations about CIBA. One of my clients asked me to help him to specify the development of one OpenID connect provider from scratch with Spring Security. Great idea ! :/

I'm convinced that it's a bad idea. Especially since there is not security experts in theirs teams... I would like to convince them that to use an open source solution like Keycloak is a good idea. Isn't it ? This merge request is already a great start :)

@ChaSophie
Copy link

Hello everybody,
I am working for a project for a french health agency that uses OpenID Connect. We think CIBA offers great possibilities. As we already use KeyCloak, I think that joining this community is an obvious step in order to keep on making progress on the project.
I am looking forward to our exchanges of knowledge and will be happy to get your inputs on my future questions and remarks.

@tnorimat
Copy link
Contributor Author

@ChaSophie Hello, CIBA is goin to be treated at FAPI-SIG. It might be helpful for you to refer to the keycloak developer's mailing list's FAPI-SIG article and FAPI-SIG's working repository. If you have comment on that, coule you please post it to the keycloak developer's mailing list?. Also, FAPI-SIG holds bi-week meetings so that you can join it to keep up with CIBA support on keycloak.

@ChaSophie
Copy link

ChaSophie commented Nov 4, 2020

@ChaSophie Hello, CIBA is goin to be treated at FAPI-SIG. It might be helpful for you to refer to the keycloak developer's mailing list's FAPI-SIG article and FAPI-SIG's working repository. If you have comment on that, coule you please post it to the keycloak developer's mailing list?. Also, FAPI-SIG holds bi-week meetings so that you can join it to keep up with CIBA support on keycloak.

Hello @tnorimat ! Thank you for these informations. I would like to join the bi-week meetings, where could I find informations about this ? Thanks

@VinodAnandan
Copy link

@ChaSophie thank you for your interest in FAPI-SIG. Could you please include your name here ( https://github.com/keycloak/kc-sig-fapi/blob/master/members.adoc ) and/or join the "keycloak-dev" mailing list ( https://groups.google.com/g/keycloak-dev ) where we sent the meeting details. The current zoom meeting details are below, but it may change so, it's always better to join the community channel to get updates.

WED 08:00 to 09:00 (GMT)  

Zoom Meeting Details: 

Meeting-ID : 957 0201 2170
Zoom Link : https://zoom.us/j/95702012170
Zoom International Dial-in Numbers : https://zoom.us/u/acGKNVHUYZ

@c4r1570p4e
Copy link

@ChaSophie Hello, CIBA is goin to be treated at FAPI-SIG. It might be helpful for you to refer to the keycloak developer's mailing list's FAPI-SIG article and FAPI-SIG's working repository. If you have comment on that, coule you please post it to the keycloak developer's mailing list?. Also, FAPI-SIG holds bi-week meetings so that you can join it to keep up with CIBA support on keycloak.

Hello @tnorimat ! Thank you for these informations. I would like to join the bi-week meetings, where could I find informations about this ? Thanks

Hello everybody,
As I'm working on the same subject as ChaSophie, I'll join to the bi-week meetings too,
Thanks

@FranckBsk
Copy link

@ChaSophie Hello, CIBA is goin to be treated at FAPI-SIG. It might be helpful for you to refer to the keycloak developer's mailing list's FAPI-SIG article and FAPI-SIG's working repository. If you have comment on that, coule you please post it to the keycloak developer's mailing list?. Also, FAPI-SIG holds bi-week meetings so that you can join it to keep up with CIBA support on keycloak.

Hello @tnorimat ! Thank you for these informations. I would like to join the bi-week meetings, where could I find informations about this ? Thanks

Hello everybody,
As I'm working on the same subject as ChaSophie, I'll join to the bi-week meetings too,
Thanks

Hello everybody,

As @c4r1570p4e, i am working with @ChaSophie on OIDC subject and I'll be one of yours at Wednesday's next meeting.

See you.

Thanks !

@tnorimat tnorimat deleted the KEYCLOAK-12137-CIBA branch February 5, 2021 04:24
@bourhisa
Copy link

bourhisa commented Jul 1, 2021

Hi everyone, I'm Arnaud from the ANS (french national agency for digital health systems).
I recently joined the agency in the same team as @ChaSophie, and I will be working along with her on OIDC subjects, among others things.

Regarding my background, I have worked for about 4 years as a security consultant, including a year in a production team in charge of federation systems (relying on SAML).

I'm super pleased to be joining the OIDC community, I hope I will be helpful and we'll work well all together
See you on next wednesday!
Cheers,
Arnaud

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.

10 participants