-
Notifications
You must be signed in to change notification settings - Fork 0
endpoints to receive/forward hq invites #51
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
Conversation
user_token = request.data["user_token"] | ||
invite_code = unquote_plus(callback_url) | ||
try: | ||
response = requests.post(callback_url, data={"invite_code": invite_code, "token": user_token}) |
Check failure
Code scanning / CodeQL
Full server-side request forgery Critical
user-provided value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you planning to address this? Given your answer below about where this points, it should be doable to check it against an allowed list (only hq instances?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have addressed this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple small questions
users/views.py
Outdated
authentication_classes = [ClientProtectedResourceAuth] | ||
|
||
def post(self, request, *args, **kwargs): | ||
callback_url = quote_plus(request.data["callback_url"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where does callback_url
come from and point to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all according to the modified spec.
This comes from HQ and it points to HQ's invite confirmation view. It's for actual invite confirmation, when mobile confirms it to ConnectID, ConnectID calls back HQ on callback_url with the user's token.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the HQ change dimagi/commcare-hq@407303f
users/views.py
Outdated
|
||
|
||
class ConfirmHQInviteCallback(APIView): | ||
authentication_classes = [ClientProtectedResourceAuth] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who makes this call? Is this not from mobile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is made by mobile.
From spec
To accept invitation (when user confirms), call below endpoint
‘connectid.dimagi.com/users/confirm_hq_invite’
POST params
callback_url: callback_url (forwarded in deep link)
invite_code: invite_code (forwarded in deep link)
user_token: user’s active auth token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, this auth is incorrect. It only works with oauth client credentials grants (what we use for connect or other servers). I think the default auth classes should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right! I will remove those classes.
@calellowitz Please let me know if this is good to go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few questions on the new code in addition to the previous comments
connectid/views.py
Outdated
@@ -28,3 +28,10 @@ def assetlinks_json(request): | |||
}, | |||
] | |||
return JsonResponse(assetfile, safe=False) | |||
|
|||
|
|||
def deeplink(request, subpath): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we able to direct them directly to the play store? That is what we discussed on the call and seems to make the most sense if it is possible. Mobile seemed to believe that it would be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -434,7 +434,8 @@ def post(self, request, *args, **kwargs): | |||
# We don't want to make this a user lookup service | |||
# So fake a success message | |||
return JsonResponse({"success": True}) | |||
deeplink = f"https://connectid.dimagi.com/hq_invite/{callback_url}/{username}/{invite_code}/{user_domain}" | |||
details = f"{callback_url}/{username}/{invite_code}/{user_domain}/{user.username}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we spoke about this a while ago, but why is this encoded as a path rather than using query params (which libraries on web and mobile could parse much more easily)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think there was some issue regarding formatting this using query params on mobile, this format was specified by mobile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spoke to @OrangeAndGreen and he seemed to believe query params would be better for them as well. Let's offline on slack about this with a mobile dev.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I have updated this to use queryparams.
@calellowitz Thanks for the review, I have followed up. |
connectid/views.py
Outdated
# and the URL is opened in the browser, ask the | ||
# user to install the app and try again | ||
return HttpResponse("Please install CommCare and re-open this link to accept invite") | ||
html_content = """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why inline HTML instead of using a separate file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved it to its own dir.
@@ -80,7 +80,10 @@ | |||
WSGI_APPLICATION = 'connectid.wsgi.application' | |||
|
|||
|
|||
|
|||
TRUSTED_COMMCAREHQ_HOSTS = [ | |||
"commcarehq.org", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how does this work? Specifically, if commcarehq.org
is enough to catch www.commcarehq.org
I would expect it to also catch staging, and if we need to be more specific, I would expect www
to be required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I will add www
to the list to be specific.
@@ -434,7 +434,8 @@ def post(self, request, *args, **kwargs): | |||
# We don't want to make this a user lookup service | |||
# So fake a success message | |||
return JsonResponse({"success": True}) | |||
deeplink = f"https://connectid.dimagi.com/hq_invite/{callback_url}/{username}/{invite_code}/{user_domain}" | |||
details = f"{callback_url}/{username}/{invite_code}/{user_domain}/{user.username}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spoke to @OrangeAndGreen and he seemed to believe query params would be better for them as well. Let's offline on slack about this with a mobile dev.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple small questions
@calellowitz I have addressed your feedback, please have a look. I think the CodeQL failure is incorrect as it is not able to detect the trusted URL check that is added. |
@calellowitz Bumping for review please. |
Thanks @calellowitz please also review the corresponding HQ PR https://github.com/dimagi/commcare-hq/pull/34967/files#diff-dc2c79b556e950acc7dea90175fd5febba22bf9fa4faaba1b61c3b3d5acdc9e9 |
Spec
Ticket