Create ClientApplication resource
# support
j
Hi team! Working with our self-hosted medplum instance that's behind our VPC, I'm wondering if there's an easy way to create a
ClientApplication
resource (and all the related resources like
Project
)? e.g. I would love if (being root user on the machine I'm ssh'ing to) I could do this with the medplum CLI. I may be missing something potentially obvious though, sorry if so. Thanks again!
r
HI @jakxz - we have an API endpoint for creating ClientApplications: https://www.medplum.com/docs/api/project-admin/client
Would love to learn more about your use case, if you don't mind sharing!
j
We're just moving our auth over from email/pw with the code challenge method to ClientCredentials to have better scoped roles and to get away from possible rate limiting issues
@rahul1 - quick question about the
User management guide
> To create a new Project resource via the API, you will need to create a ClientApplication with super admin privileges. > > DANGER > Super admin features can cause unrepairable damage. We highly recommend adding an Access Policy to this ClientApplication to reduce it's privileges. > > With is ClientApplication, you can create a Project resource and invite the a new user as a project admin. However, it seems like I need a Project before I can create a [scoped] ClientApplication? https://github.com/medplum/medplum/blob/af9e511b29f27088ff2f59c8a8d51722ebc67e14/packages/server/src/admin/project.ts#L17
cc @cody sorry to tag directly but I am a bit turned around here 😅
r
Hi @jakxz , do you mind walking me through your end to end use case? I think we might be talking past each other
j
No worries I'm probably not being clear. We have the medplum API server deployed without the Medplum UI, and we are using this server to store FHIR bundles [to the underlying medplum db in postgres]. To authenticate with this server, we've been using the authorization code flow with an email + pw + code & code challenge. We read in the docs that there might be rate limiting applied to requests using this approach so since we're starting to run more traffic through the part of our application that stores and retrieves data from our Medplum server we figured we should switch to the ClientCredentials flow to auth requests. To do that, we need a
ClientApplication
to get a
client_id
and
client_secret
that we can use for the ClientCredentials flow. And that seems to require a
Project
.
does that make sense? Is our concern even valid?
r
Ah got it! Do you mind pointing me to the docs you read about rate limits? I just want to double check the language
TL;DR, we do rate limit auth requests, but the method of authentication doesn't make a difference
For server-to-server interactions, Client_credentials would be the way to go (or Basic Auth).
r
Got it! Just FYI, that section is more for use cases where a physical devices, like lab equipment, is connected to medplum 😄 If you're just doing webserver to webserver communication. this section is probably more applicable
Either way, client creds probs the way to go
I think I'd break down your problem into 2 scenarios; 1. You want to put all the Bundles into a single Medplum Project (https://www.medplum.com/docs/auth/user-management-guide#users-and-projects). IN that case, you can create a
ClientApplication
within the Project of interest
2. You want to have a clientId that can create projects. This means that you need a CLientApplication that "sits above" a single project. In this case, it needs to be a "super admin" ClientApplication. Everything with "SuperAdmin" priveledges sits in a special project called Super Admin. You can read more about SuperAdmin here: https://www.medplum.com/docs/self-hosting/super-admin-guide
j
naive question, how might I query my superadmin project? Might I already have a client id and secret that I could use?
r
I see, because you don't have the medplum UI set up. This is a pretty uncommon pattern, but it's definitiely possible. Every project has a ClientApplicaiton created by default, including the SuperAdmin project. You can query it just like any other resource after you've logged in via auth code flow
The endpoint I linked above can be used to create new ClientApplications
that being said, I'd recommend setting up the medplum app. Makes this kind of administration much easier 🙂
j
I assumed that creating a
ClientApplication
within the Super Admin project would work in the way you're describing in this first option
but I think I'm still missing something 😓 because we're seeing unauthorized errors* for requests now trying to store Bundles with the Client id and secret from the
ClientApplication
resource I made
r
Hi @jakxz , I'm sorry about that. Do you mind walking me through what you tried? Some questions: - Are you creating a new ClientApplication in a new Project, or in the SuperAdmin project? - What API call did you make to create the ClientApplication? - Did you try querying the default ClientApplication?
j
1. I created the ClientApplication within the super admin project
2. I POSTed to
/admin/projects/:projectId/client
to make the ClientApplication [and got a successful response with the id and secret, and seemingly properly linked to the super admin project]
3. I didn't know there was one - where could I find that? sorry if I wasn't clearer earlier but I thought I'd asked about that 😅
r
Oh sorry, I thought the default one wasn't sufficient, which is why you were creating a new one
So ClientApplications are just FHIR resources, so you can GET and POST them just like any other resource
j
right
and when I did
select * from "ClientApplication";
before creating the one I did, I saw no rows returned
r
ok, let me just double check something - the super admin project has some default behavior that is non-standard
Ok sorry for the confusion. - When you create a new project via the UI, we do some convenience operations for you. One of them is to set up a new ClientApplication, called the default Application - But the SuperAdmin project "sits above" the projects, and doesn't get this behavior. - One thing you can try is just POSTing to
/ClientApplication
to create a new one
One more thing to check - does the ClientApplication you created before allow you to store simple resources like "Patient"?
Just want to make sure there's not another underlying issue
j
sure - how can I verify that?
r
POST /Patient [body], where the [body] is a Patient resource in JSON form
j
and sorry if this is a given, when I do that, how do I know that I am testing against the ClientApplication?
based on the client credentials?
r
yeah, use the ClientApplication to perform the client credentials login flow and get an access token: https://www.medplum.com/docs/auth/client-credentials
j
if so we might already have the answer - we are seeing unauthorized errors trying to do this
although we were POSTing to
/
not
/Patient
interestingly
r
are you sending the access token?
j
I think so 🤞🏾
r
kk - another sanity check. Are you able to post to
/Patient
using Basic Auth?
Also, we tend to send back an error in the body of the 401 response. Are you able to see anything?
Sorry for the basic questions - i'm a bit confused about the behavior your seeing
j
🤔 hmm looks like we were getting invalid client
no worries these are great, helpful to know where to poke
really appreciate the eyes on this
r
My guess is that the projectMembership didn't get created properly. Again - doing all this in the superAdmin project is not really the recommended path
This is the code that gets called endpoint that gets called when you do that: https://github.com/medplum/medplum/blob/main/packages/server/src/admin/client.ts#L42-L67
j
This is meant to be a different link right? I'm just digging around for the code for* creating a project membership now
r
yes! edited
j
interesting, yeah, I would've expected that to have been called when I POSTed to
/admin/projects/:projectId/client
r
yes, it's the same code path
/admin/projects/:projectId/client, you said you're getting the ClientApplication resource?
j
yes
r
Can you query
GET /ProjectMembership
with your existing login, to make sure the membership is created?
j
is that at
/admin/projects/:projectId/membership
?
r
Not, just
GET /ProjectMembership
. ProjectMembership is also just a resource
j
cool
got a bundle back
r
Do any of them have a reference to your client application?
j
yes
r
Ok, so it's not missing a membership 🤔
Do you mind DM'ing me the specific HTTP request you're making that led to "invalid_client", along with all the headers?
client secrets are considered sensitive, so don't want to post in this forum
j
👍🏾
@rahul1 hey! Sorry for the slow reply here. TLDR I have a PR for you but I might be completely wrong 😅 https://github.com/medplum/medplum/pull/2712 as we discussed in DM I was able to successfully get an access token from the server with the
ClientApplication
resource's id and secret. still no idea what changed 😕 but this is all good now To answer your question from earlier, I was not using the typescript client because we wanted to handle the response directly for some
PATCH
&
PUT
operations in specific ways, without any of the (retrying/error) logic under the hood that the medplum client does. however, I realized that for the last operation we are doing, we can totally use the typescript client and it seemed to work when I had my medplum server running locally.... but I think this PR might solve the issue I am now seeing
r
Thank you so much for the PR! This was definitely a miss on our end.
Also, if there's additional configuration params you'd like to see for the MP client (e.g. configurable retries), feel free to file an issue or PR - that would be a very reasonable modification
162 Views