OIDC Authenticator - Doesn't seem to honor expiry

When using the OIDC authenticator, I noticed that the authenticator still succeeds even if we’re past the expiration time designated in the JWT.

While not doing a comprehensive validation of the JWT may be okay, it does seem strange that the authenticator doesn’t deny when the token expires - we lose a large amount of the value when it can’t be used as a ‘short lived’ access token, but continues to be valid for access indefinitely.

What I haven’t tested either is whether or not JWT token is verified as being signed by the right provider, is it?

2 Likes

This should definitely be added to the oidc-authn.
Do you think this should be configurable or should it be mandatory? I think this should be mandatory to validate the expiration token.

Adding this ability should look something like:

def jwt_expiration
 @expiration_time ||= @id_token_attributes["exp"]
end

def current_epoch
 @current_epoch = Time.now.to_i  
end

def validate_jwt?
 current_epoch < jwt_expiration
end

Andrew

The question here might be also if the OIDC provider should be responsible for checking the expiry time. We could try to verify as well but it almost seems like this should be a feature of the OIDC verification. From a cursory look it does seem to me that this is expected to be done on the server: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html#API_AssumeRoleWithWebIdentity_Errors

Thats what I was also thinking, it is kind of odd if the STS is not validating the expiration date.

Andrew, that does seem like it should probably be mandatory since it’s a pretty important part of the specification.

Regarding who should be doing the validation - I’m not particularly savvy at Ruby so I may be reading the conjur code incorrectly. The STS flow is quite a bit different - the way the IAM authenticator works does indeed prevent it, but that’s because AWS is basically an active participant in the model Conjur uses there and isn’t really OIDC.

While I think I see the retrieval of the provider certificate in your ruby module, I’m not seeing anything around invoking theintrospection endpoint, so there wouldn’t be an opportunity for the OIDC provider to run the expiration validation as you suggest. Honestly, it’s really not worth doing the introspection (see OKTA’s comment), as it’s complexity for very little value thanks to the signed token being a good proof of identity anyway - your proposal makes a lot of sense.

OKTA does also outline best validation practices. Since Conjur isn’t really doing a full OIDC flow, the only verification beyond what you’re doing that is probably still relevant would be the iat (is in the past) and exp (is in the future). A audience check would probably be best practice, but a lot of common validators out there don’t check that anyway.

Hi martin,

We do validate the ID Token expiration,
Can you send me the following in order to understand why id didn’t work for you:

  1. The oidc authenticator policy
  2. The Conjur debug logs of sending an expired id token (JWT) to conjur
  3. The JWT token

Thanks,
Nessi

The JWT’s a bit of a password, so not particularly comfortable with that. We can do a demo instead, though (or provider the debug / policy only)

Here, this may work:
OIDC policy

- !policy
  id: conjur/authn-oidc/okta
  body:
  - !webservice
    annotations:
      description: Authentication service for okta, based on OpenID Connect.
 
  - !variable
    id: provider-uri
 
  - !variable
    id: id-token-user-property
 
  - !group
    id: users
    annotations:
      description: Group of users who can authenticate using the authn-oidc/okta authenticator
  - !permit
    role: !group users
    privilege: [ read, authenticate ]
    resource: !webservice

Variable sets

- conjur variable values add conjur/authn-oidc/okta/provider-uri https://myorgdev.oktapreview.com/
 	
- conjur variable values add conjur/authn-oidc/okta/id-token-user-property initials

Conjur Log - let me know what settings we should set for the right level of logging

The decode of the id token being sent as my id_token:

{
  "sub": "00u6e37o0iElt0Lnt0h7",
  "name": "Martin Pieters",
  "email": "Martin.Pieters@myorgdev.com",
  "ver": 1,
  "iss": "https://myorgdev.oktapreview.com/oauth2/auso8wc9p4E2m0K950h7",
  "aud": "0oao8tg4vuCbLmPAi0h7",
  "iat": 1574039644,
  "exp": 1574043244,
  "jti": "ID._Lb2hNGSqRTkPIVf_TvFN8y0nG-ZUeZ8OuEZNKH5mDI",
  "amr": [
    "pwd"
  ],
  "idp": "0oa2nnid0pKGQPAZOSDD",
  "nonce": "1eztcyh",
  "preferred_username": "XXXX@myorgdev.com",
  "auth_time": 1574039586,
  "at_hash": "wEdF1fwd62dau0Oey4pnxQ",
  "initials": "XXXX"
}

I waited longer past expiry (tried it today again with the same id token - 12 hours) and it is indeed flagging as expired. Must be a clock issue on our docker node. I had tried with it being expired ~10 minutes, and it still authenticated.

What would I enable to debug the OIDC authentication? Turns out the OIDC token isn’t usable by Conjur for the first minute of its existence right now for us, either.

Yes this is the issue, thanks i will add it to troubleshooting section.

However in order to enable conjur server logs please follow the commands in our docs under
“Troubleshooting OIDC authentication” section.

Example of the logs with ID Token expired error:

DEBUG 2019/11/19 01:54:17 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00023D Concurrency limited cache concurrent requests updated to '1'

DEBUG 2019/11/19 01:54:17 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00007D Working with OIDC Provider https://dev-842018.oktapreview.com

DEBUG 2019/11/19 01:54:18 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00008D OIDC Provider discovery succeeded

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00009D Fetched OIDC Provider certificates successfully

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00016D Rate limited cache updated successfully

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00021D Concurrency limited cache updated successfully

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00023D Concurrency limited cache concurrent requests updated to '0'

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00017D OIDC Provider certificates fetched successfully from cache

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] CONJ00005D ID Token decode succeeded

DEBUG 2019/11/19 01:54:19 -1000 [pid=335] [origin=172.22.0.1] [request_id=bdcfda5d-4f51-4643-91d3-091718326deb] [tid=341] Authentication Error: #<Errors::Authentication::AuthnOidc::IdTokenExpired: CONJ00016E ID Token expired>
2 Likes

Thanks, we’ll troubleshoot further. Since there isn’t actually someone amiss with the platform here, I"ll close this and monitor our setup further.

I’ve also submitted a PR to provide OIDC integration for the golang library

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.