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

Customizable TTL per OAuth2 Client #3157

Closed
5 of 6 tasks
aeneasr opened this issue Jun 15, 2022 · 8 comments
Closed
5 of 6 tasks

Customizable TTL per OAuth2 Client #3157

aeneasr opened this issue Jun 15, 2022 · 8 comments
Assignees
Labels
feat New feature or request.

Comments

@aeneasr
Copy link
Member

aeneasr commented Jun 15, 2022

Preflight checklist

Describe your problem

It is not possible to set varying TTLs per OAuth2 Client, only globally. This is not practicable in regulated environments.

Describe your ideal solution

Be able to set the TTL of different OAuth2 Flows per OAuth2 Client. This functionality would not be available for OIDC Dynamic Registration but only when using the administrative OAuth2 Client management endpoints.

Optimally, the configuration would be part of the HTTP REST request for a new endpoint:

PUT /clients/<id>/lifespans

{
  "grants": {
    "authorize_code": {
      "id_token": "1h"
    }
    "refresh_token": {
      "access_token": "1h"
    }
    "client_credentials": {
      "access_token": "1d"
    }
  }
  // ...
}

This is a "safer" method of controlling these highly privileged fields. For example, this endpoint could be only available to certain callers and dis/enabled in some type of firewall.

Additionally, it allows us to stray from the OIDC Dynamic Client Registration spec as it's an additional endpoint and we have more freedom in designing it and its responses.

Workarounds or alternatives

Optionally, the configuration would be part of the HTTP REST Request:

POST /clients

{
  "client_secret": "..."
  // ...
  "token_lifespans": {
    "access_token": ...
    "reresh_token": ...
    // ...
  }
}

This option is not preferred and should be avoided

Part of clients endpoint

This could be part of the /clients endpoint, with the caveat that it doesn't follow oidc client registration conventions.

POST /clients

{
  "client_secret": "..."
  // ...
  "token_lifespans": {
    "access_token": ...
    "reresh_token": ...
    "grants": {
      "client_credentials": {
        // Overrides value from above
        "access_token": ...
      }
    }
  }
}

Flat payload

The following payload would feel more OAuth2-y:

POST /clients

{
  "client_secret": "..."
  // ...
  "access_token_lifespan": ...
  "id_token_lifespan": ...
}

but it is also harder to define more granular controls like client_credentials grant has 1h and authorize_code grant has 1d lifespan.

TTL per Consent

Set the TTL per consent. This would also be possible, but does not cover non-browser flows such as the OAuth2 Client Credentials flow or some other token exchange flows.

Version

v1.x

Additional Context

No response

@aeneasr aeneasr added the feat New feature or request. label Jun 15, 2022
@aeneasr
Copy link
Member Author

aeneasr commented Jun 15, 2022

Implementation is a bit weird and needs to be tested as this feature has taken a back seat for a long time. Basically, we'll need to add some code around

which would be something along the lines of:

	if c, ok := accessRequest.GetClient().(*client.Client); ok {
		if c.TheAccessTokenLifespan.Valid {
			session.SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(c.TheAccessTokenLifespan.Time))
		}
		// ...
	}

This of course needs testing in oauth2/oauth2_auth_code_test.go, oauth2_client_credentials_test.go and of course testing the HTTP handler itself also which is setting these keys.

Additionally, we'll need some SQL migrations to add these new keys to the OAuth2 Client's database model that also need to be tested and backported to the v2.x branch.

Lastly, this needs e2e tests which cover the functionality already tested in the integration tests in the oauth2 package. This is the last sanity check that everything works e2e.

Finally, this has to be documented and announced (/cc @kmherrmann ).

@aeneasr
Copy link
Member Author

aeneasr commented Jun 23, 2022

Potentially related: https://github.com/ory/fosite/pull/656/files

@aeneasr
Copy link
Member Author

aeneasr commented Jun 28, 2022

You can also play around with it in fosite itself first here: https://github.com/ory/fosite-example/blob/master/authorizationserver/oauth2_token.go

@aeneasr
Copy link
Member Author

aeneasr commented Jun 28, 2022

The client migrations in 1.x needs to be backdated so it ends up in the correct order in v2.x

@grantzvolsky
Copy link
Contributor

Note to self: make sure to backdate the migrations before 2.x migrations

@grantzvolsky
Copy link
Contributor

Hi @aeneasr @piotrmsc . I had a look at fosite and Hydra's usage of it, and this is the simplest solution I could find. Please let me know what you think.

Customizable TTL per OAuth2 client implementation:

Fosite

  • Checkout fosite@master
  • Make sure all tests pass before making any changes
  • Update fosite's Client interface to add GetGrantLifespan(gt fosite.GrantType, defaultLifespan time.Duration) time.Duration
    • Initially, return a static value in storage implementations
  • Find all references to SetExpiresAt and call them with the return value from GetGrantLifeSpan
  • Make sure the tests we don't expect to pass anymore don't pass
  • Add 'SetGrantLifespans' to the storage interface & implement it
  • Implement GetGrantLifespan
  • Write unit tests & make sure all tests pass

Hydra

  • Checkout Hydra version [???] and add a mod replace to depend on the updated fosite
  • Add migrations and a test migration, all backdated to before the first 2.x migration
  • Implement the new fosite storage interface
  • Add the PUT /clients//lifespans endpoint described above by @aeneasr
  • Add an e2e test

@aeneasr
Copy link
Member Author

aeneasr commented Jul 4, 2022

Great analysis, sounds good @grantzvolsky !

grantzvolsky added a commit that referenced this issue Jul 28, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

Part of #3157
aeneasr pushed a commit that referenced this issue Jul 28, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

Part of #3157
aeneasr added a commit that referenced this issue Jul 28, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
grantzvolsky added a commit to grantzvolsky/fosite that referenced this issue Jul 30, 2022
This change introduces the ability to control the lifespan of tokens for each valid combination of Client, GrantType, and TokenType.

Part of ory/hydra#3157
grantzvolsky added a commit that referenced this issue Jul 31, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
grantzvolsky added a commit that referenced this issue Aug 1, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
aeneasr added a commit that referenced this issue Aug 1, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
@aeneasr
Copy link
Member Author

aeneasr commented Aug 3, 2022

Resolved and released!

@aeneasr aeneasr closed this as completed Aug 3, 2022
aeneasr added a commit that referenced this issue Aug 18, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
aeneasr added a commit that referenced this issue Sep 5, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
aeneasr added a commit that referenced this issue Sep 7, 2022
This change introduces a new endpoint that allows you to control how long client tokens last. Now you can configure the lifespan for each valid combination of Client, GrantType, and TokenType.

See #3157

Co-authored-by: aeneasr <[email protected]>
Co-authored-by: Andreas Bucksteeg <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request.
Projects
None yet
Development

No branches or pull requests

2 participants