Automatically authenticate required applications during web app auth#45512
Automatically authenticate required applications during web app auth#45512
Conversation
7b151e8 to
eb9b0d9
Compare
cccf9d8 to
478244d
Compare
478244d to
3f18fbe
Compare
3f18fbe to
fa8c486
Compare
9f31667 to
7fdc1f6
Compare
|
🤖 Vercel preview here: https://docs-4ny5njkol-goteleport.vercel.app/docs/ver/preview |
|
@ryanclark could you give this one a look when you get the chance please 🙏 . Security review came back good so this is ready |
flyinghermit
left a comment
There was a problem hiding this comment.
LGTM based on the decision that this is the way we want to implement the feature.
Left a few suggestions on renaming and reducing extra request steps.
| // GetIntegration will return the Integration. | ||
| // If present, the Application must use the Integration's credentials instead of ambient credentials to access Cloud APIs. | ||
| GetIntegration() string | ||
| // GetRequiredApps will return a list of required apps public addrs that should be authenticated during this apps authentication process. |
There was a problem hiding this comment.
// GetRequiredApps will return a list of required apps public addrs
Does this return public addrs or app name?
| // This field is used to preserve the original requested path through | ||
| // the app access authentication redirections. | ||
| path string | ||
| // requiredApps is a list of required app names to be used during application |
There was a problem hiding this comment.
// requiredApps is a list of required app names
At this point, the value of requiredApps is fqdn and not app name right?
| // requiredApps is a list of required app names to be used during application | |
| // requiredApps is a list of required app fqdn to be used during application |
There was a problem hiding this comment.
I think it would also be good to update the names so distinction is clear?
requiredAppsNamein the app configuration spec andrequiredAppsFQDNhere
| type GetAppDetailsResponse struct { | ||
| // FQDN is application FQDN. | ||
| FQDN string `json:"fqdn"` | ||
| // RequiredApps is a list of required app names |
There was a problem hiding this comment.
fqdn here too?
| // RequiredApps is a list of required app names | |
| // RequiredApps is a list of required app FQDN |
| } | ||
|
|
||
| let requiredApps = resolvedApp.requiredApps || []; | ||
| if (isRedirectFlow !== null) { |
There was a problem hiding this comment.
nit:
| if (isRedirectFlow !== null) { | |
| if (!!isRedirectFlow) { |
(unless you want to make it clear that we are explicitly checking for null :) )
There was a problem hiding this comment.
Specifically checking for null because redirectFlow is got from queryParams.get which returns null or string. (also, the double negation throws eslint here based on string type so, i'll leave this one)
| // GET /v1/webapi/apps/:fqdnHint/:clusterName/:publicAddr | ||
| func (h *Handler) getAppFQDN(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *SessionContext) (interface{}, error) { | ||
| req := GetAppFQDNRequest{ | ||
| func (h *Handler) getAppDetails(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *SessionContext) (interface{}, error) { |
There was a problem hiding this comment.
suggestion: If we can send required apps (fqdn) in the app response from the unified resource api, we can collapse the first two requests we have now to one.
- First request
/web/launch...? - Second request
webapi/appsresponds with required apps - Third request
/web/launch...?required-apps=<required app from responds received in second request >.
I can see this URL was always called to get the app fqdn which I do not understand why it was done that way. Up to you if you want to reduce number of requests here.
There was a problem hiding this comment.
That or looks like we cna also combine the state and required apps response to one, which would reduce few extra requests.
There was a problem hiding this comment.
Agree, but I will TODO this for now. I'd like to talk to @capnspacehook to make sure this extra call can be merged with the first. Really like this idea a lot
most of the /web/launch/ calls are from a redirect and not a direct api call so sending the data back might be a bit weird but I'll explore it
7fdc1f6 to
0c34e17
Compare
|
🤖 Vercel preview here: https://docs-faqodnc7t-goteleport.vercel.app/docs/ver/preview |
0c34e17 to
6dc1fcb
Compare
|
Im not sure what happened, but a bunch of other changes got scooped up when i did |
|
🤖 Vercel preview here: https://docs-bgt920ijl-goteleport.vercel.app/docs/ver/preview |
6dc1fcb to
4698e76
Compare
|
🤖 Vercel preview here: https://docs-5oxjb7sll-goteleport.vercel.app/docs/ver/preview |
part of: #17588
This app fixes the issue where a user would have to manually click the "launch" button for every app that another app may require to work (for instance, a backend API for a client side react app).
The solution is to have admins set a "required apps" field in their app spec, which will allow the app handler and client to automate the authentication redirects when launching the desired app. This value is passed through a query param through the authentication flow and used by the server to determine which app to redirect to next, ultimately landing on the originally requested app.
security considerations
Although this query param can be "user supplied", it does not bypass any of the current authentication flow and goes through the same validation as if it were clicked from the "Launch" button in the Web UI. It is used merely as an indication of which URL to build.
Scenarios checked (please let me know if I've missed any)
Example breakdown
the app named
clientrequires the appapito serve it static assetsExample old flow:
-> The user would authenticate to Teleport.
-> The user would click "Launch" for
client.->
clientwould go through the redirect flow->
clientwill be authenticated and load. However, assets would not load becauseapiis not authenticated.-> user goes back to teleport, clicks "Launch" on
api, and goes through the redirect flow->
clientnow works as expected.-> repeat above for any other required apps
New flow
-> The user would authentication to Teleport
-> The user would click "Launch" for
client->
clientwill instead go through the redirect flow for any of the required apps.-> once all the required apps are done, the last redirect is for
client->
clientworks as expected.This essentially boils down to automatically going to all the correct
/web/launch/:fqdnURLs in the browser and nothing more.Example of my app service
This PR will not solve the preflight CORS requests if
client.teleport.zarquon.shis trying to accessapi.teleport.zarquon.shwith some sort of custom header (such asAuthorization) because currently, we do not accept non-authenticated requests (OPTIONSrequests are always unauthenticated). That PR will come after.You can use this repo for local apps to test with https://github.com/avatus/corstest
changelog: You can now set required app names in your application spec. This will enable the Web UI to automatically authenticate every app required during application authentication.