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

Feat: Configure refresh token expiry #4525

Merged
merged 8 commits into from
Jun 11, 2024

Conversation

thejwuscript
Copy link
Contributor

Related to issue #4409

This PR allows project admins to optionally configure the expiry of a refresh token for a ClientApplication.

A refreshTokenExpiry field is added to the ClientApplication resource. The field is optional to allow backward compatibility. The value is used to generate the exp claim on a refresh token.

UI changes to the Medplum App is not addressed in this PR; it can be included here if necessary, or be made on a separate PR.

@thejwuscript thejwuscript requested a review from a team as a code owner May 7, 2024 15:36
Copy link

vercel bot commented May 7, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
medplum-provider ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 11, 2024 7:32am
3 Ignored Deployments
Name Status Preview Comments Updated (UTC)
medplum-app ⬜️ Ignored (Inspect) Visit Preview Jun 11, 2024 7:32am
medplum-storybook ⬜️ Ignored (Inspect) Visit Preview Jun 11, 2024 7:32am
medplum-www ⬜️ Ignored (Inspect) Visit Preview Jun 11, 2024 7:32am

Copy link

vercel bot commented May 7, 2024

@thejwuscript is attempting to deploy a commit to the Medplum Team on Vercel.

A member of the Team first needs to authorize it.

"min" : 0,
"max" : "1",
"type" : [{
"code" : "date"
Copy link
Contributor

Choose a reason for hiding this comment

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

for our use case we'd like to specify a value here which is relative to the current time, not a fixed date parameter.

the expiration value is passed to the jose npm package, which treats number and Date values as the fixed expiration time in the claim (reference here), however string values are converted to a time span relative to the current time (reference here) - which matches the existing behaviour with the 2w default.


i think ideally this property would be a string which could either support the full range of jose formats, or perhaps a subset of this (to allow for easier validation in the medplum middleware)

Copy link
Member

Choose a reason for hiding this comment

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

Yes I think if we can change the name of this field to refreshTokenLifetime and make it an expiry duration as a string (eg. '2w', '1h', etc.) that maps to jose formats as @josh- pointed out, that would be ideal 👍

Copy link
Member

Choose a reason for hiding this comment

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

@thejwuscript - just wanted to make sure you saw the above comment from @ThatOneBro . This is our main feedback on the PR

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, thanks very much for the feedback. I'll be making the changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

@thejwuscript do you know when you'll be able to make those changes? let me know if I can help. eager to be able to use this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@josh- I'll try get it done by Monday.

Copy link
Member

@ThatOneBro ThatOneBro left a comment

Choose a reason for hiding this comment

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

Looks good for the most part! Consulting with @mattwiller about where the validation should occur. Once we figure that out we should be good to go! Thanks again for your help @thejwuscript! 😄

@@ -117,6 +118,9 @@ protectedRoutes.use('/bulkdata', bulkDataRouter);
// Async Job
protectedRoutes.use('/job', jobRouter);

// Validate data before updating ClientApplication
protectedRoutes.put('/ClientApplication/:id', saveClientValidator);
Copy link
Member

@ThatOneBro ThatOneBro Jun 10, 2024

Choose a reason for hiding this comment

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

I'm thinking this probably should not be directly in an express route, should probably be done at the FhirRouter level potentially? What do you think, @mattwiller?

I know we have talked about doing something like this across the board long term (having specific validation on a per resource basis, maybe via some "prewrite" pass)

That's definitely out of scope for this PR but would be nice to move in a more uniform direction

Copy link
Member

Choose a reason for hiding this comment

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

I would actually propose moving this validation into the field definition itself, using a FHIRPath condition like this:

 {
  "id" : "ClientApplication.refreshTokenLifetime",
  "path" : "ClientApplication.refreshTokenLifetime",
  "definition" : "Optional configuration to set the refresh token duration",
  "min" : 0,
  "max" : "1",
  "type" : [{
    "code" : "string"
  }],
  "constraint" : [{
    "key" : "clapp-1",
    "severity" : "error",
    "human" : "Token lifetime must be a valid string representing time duration (eg. 2w, 1h)",
    "expression" : "$this.matches('^[0-9]+[smhdwy]$')"
  }],
  "base": {
    "path" : "ClientApplication.refreshTokenLifetime",
    "min" : 0,
    "max" : "1"
  }
}

That way, this validation gets performed at the Repository level, any time the resource is updated anywhere in the system.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I actually agree, this is probably the right way to do it

@ThatOneBro
Copy link
Member

Okay I pushed a tweak applying @mattwiller's suggestion and some tests for some specific cases, after someone else approves we can push this through. Thank you @thejwuscript for taking this issue 🙏

@ThatOneBro ThatOneBro added this pull request to the merge queue Jun 11, 2024
@ThatOneBro ThatOneBro self-assigned this Jun 11, 2024
@ThatOneBro ThatOneBro added the auth Authentication and authorization features and fixes label Jun 11, 2024
Merged via the queue into medplum:main with commit 35e34fd Jun 11, 2024
28 of 31 checks passed
medplumbot added a commit that referenced this pull request Jun 21, 2024
## What's Changed

fix(ci): fix `\n` missing due to reversal, use `git log --reverse` (#4649)
Allow chained search in _filter (#4647)
Polish eligibility demo (#4637)
cleanup(core): remove stray `console.log` (#4653)
Update sidebar.ts (#4652)
Feat: Configure refresh token expiry (#4525)
Dependency upgrades 2024-06-10 (#4650)
cleanup(chart-demo): rm ignored `example-bots.json` (#4656)
 Adding instructions to the example app READMEs on how to build bots (#4660)
Update useSearch.ts (#4663)
Export QuestionnaireFormContext and QuestionnairePageSequence from QuestionnaireForm (#4664)
Add `expo-polyfills` to README packages list (#4666)
revert(react): remove export of `QuestionnairePageSequence` (#4669)
Fix wrong pipe character in README (#4671)
Document Terminology Service operation endpoints (#4665)
Dependency upgrades 2024-06-17 (#4673)
Gracefully handle no major dep upgrades (#4675)
SQL on FHIR ViewDefinition types (#4674)
fix(build) Update deprecated import assertion into import attribute (#4682)
Fixes #4398 - add mapByIdentifier util function (#4635)
Fixes #4600 - Add Auto Confirmation Parameter for Headless Deployment (#4625)
fix(react-hooks): make `loading` track `MedplumClient#isLoading()` (#4677)
Implements FHIRPath string join (stu) (#4683)
SQL-on-FHIR processResource (#4678)
feat(useSubscription): add `subscriptionProps` as optional param (#4180)
Resolve conditional references (#4633)
feat(subscriptions): add `unbind-from-token` message for WebSocket subscriptions (#4672)
Document remaining Terminology Service operations (#4680)
feat(agent): add `keepAlive` setting to `Agent` (#4657)
Update README.md (#4687)
Fix all copyright dates (#4689)
Fixes subject input on PlanDefinitionApplyForm (#4699)
Deprecate non-strict mode (#4651)
Validate certain references with systemRepo (#4700)
docs(useSubscription): clean up examples, add JSDoc comment (#4692)
cleanup(repo): `handleMaybeCacheOnly` -> `handleStorage` (#4696)
Minor fixes to Eligibility Demo (#4703)

**Full Changelog**: v3.1.8...v3.1.9
github-merge-queue bot pushed a commit that referenced this pull request Jun 22, 2024
## What's Changed

fix(ci): fix `\n` missing due to reversal, use `git log --reverse` (#4649)
Allow chained search in _filter (#4647)
Polish eligibility demo (#4637)
cleanup(core): remove stray `console.log` (#4653)
Update sidebar.ts (#4652)
Feat: Configure refresh token expiry (#4525)
Dependency upgrades 2024-06-10 (#4650)
cleanup(chart-demo): rm ignored `example-bots.json` (#4656)
 Adding instructions to the example app READMEs on how to build bots (#4660)
Update useSearch.ts (#4663)
Export QuestionnaireFormContext and QuestionnairePageSequence from QuestionnaireForm (#4664)
Add `expo-polyfills` to README packages list (#4666)
revert(react): remove export of `QuestionnairePageSequence` (#4669)
Fix wrong pipe character in README (#4671)
Document Terminology Service operation endpoints (#4665)
Dependency upgrades 2024-06-17 (#4673)
Gracefully handle no major dep upgrades (#4675)
SQL on FHIR ViewDefinition types (#4674)
fix(build) Update deprecated import assertion into import attribute (#4682)
Fixes #4398 - add mapByIdentifier util function (#4635)
Fixes #4600 - Add Auto Confirmation Parameter for Headless Deployment (#4625)
fix(react-hooks): make `loading` track `MedplumClient#isLoading()` (#4677)
Implements FHIRPath string join (stu) (#4683)
SQL-on-FHIR processResource (#4678)
feat(useSubscription): add `subscriptionProps` as optional param (#4180)
Resolve conditional references (#4633)
feat(subscriptions): add `unbind-from-token` message for WebSocket subscriptions (#4672)
Document remaining Terminology Service operations (#4680)
feat(agent): add `keepAlive` setting to `Agent` (#4657)
Update README.md (#4687)
Fix all copyright dates (#4689)
Fixes subject input on PlanDefinitionApplyForm (#4699)
Deprecate non-strict mode (#4651)
Validate certain references with systemRepo (#4700)
docs(useSubscription): clean up examples, add JSDoc comment (#4692)
cleanup(repo): `handleMaybeCacheOnly` -> `handleStorage` (#4696)
Minor fixes to Eligibility Demo (#4703)

**Full Changelog**: v3.1.8...v3.1.9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth Authentication and authorization features and fixes
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

None yet

6 participants