bserdar / took

OIDC Token manager CLI
Apache License 2.0
6 stars 5 forks source link

PKCE Support #12

Closed sgayou closed 4 years ago

sgayou commented 6 years ago

PKCE support may prove beneficial. I'm unclear of the likelihood of an attacker registering or taking over a URI on Linux/Windows/Mac, but it seems possible.

Here's more detail: https://openid.net/2015/05/26/enhancing-oauth-security-for-mobile-applications-with-pkse/

Here's an example:

Firefox does support opening custom, system register URIs. (man uri). As an example, we can open man:ls in Firefox and it will prompt and ask if we want to open that URI in Help.

So took theoretically could support custom URIs on the system. I.e. if I set my callbackurl to man:ls (just an example to send the token to a system app), the took flow will send me to the authorization server, verify, then redirect me back to help. If I allow firefox to open the system application, I get this:

Document Not Found
The URI ‘man:?code=<code>&state=ivhvKDSmaIRXjo222sZU-_H3utO0zJPBi8IjFwyt7tc%3D’ does not point to a valid page.

which is pretty neat. Thus, the attack that PKCE defends against is if an attacker somehow (let's say via a malicious app in a repository) registers for the same URI. I'd need to check, but I believe it could potentially overwrite others set and a malicious app could steal the code.

Of course, if you have a malicious app on the system, it could most likely just read .took.yaml and you certainly have other, bigger issues. This may be a good step for defense in depth though.

bserdar commented 6 years ago

Took doesn't follow the redirect it receives after authentication. It gets token/code info from the redirect url, but never goes there.

Is this still a problem, then?

sgayou commented 6 years ago

I believe so. After the user authenticates with the authorization server, the server will redirect the user back to the callbackurl.

For example, in my okta test setup, I have to login to my okta instance, then the okta authorization server immediately redirects me (on success) to the callbackurl. In the took callflow, the user would copy the resultant link then paste it back into took. We can set the callbackurl to anything, and as long as we have it setup inside of okta to be trusted, okta will happily redirect us there. I had it redirecting us to https://www.example.com, which is obviously bad as we don't control that domain, but it was just a test.

Thus, someone would have to setup took with a custom callbackurl pointing to what would likely be a custom URI with a custom application handling it, and the custom application would have to pop up a copyable field such that the user could then get that data back to took to complete the flow. After further reflection, that does seem highly unlikely at the moment, but it seems like a valid threat.

This is much more obvious on IOS. See: https://stackoverflow.com/questions/4758292/more-than-one-app-has-same-url-identifier-for-custom-url-application/18968258

It appears that an attacker/malicious dev could release an app that attempts to register the same URI handler as another, real app using OIDC. If the fake/malicious app gets the token from the callback, game over. PKCE prevents that attack.

I'll think more on it.

bserdar commented 6 years ago

Ok, that's a problem when you use that flow. It'll be the browser receiving that redirect. I have to take a deeper look to see how we can prevent that.

That said, there is another took flow where you define the structure of the login form of the auth server, and took receives the form, parses it, asks the user for the password, submits the form, and thus receives the redirect without any browser involvement. That flow is safe, I think. That's what we're using for RH servers.

sgayou commented 6 years ago

My current understanding is the above functionality is correct. Took is the client app, and the client app has to get the token back from the authorization server. Thus, the redirect gets us the token. Let me know if that's wrong.

Didn't have time to test the other flow unfortunately, so no feedback on that. Sounds good over TLS. Once it rolls out, toss me an e-mail and I'll check it out in some free time.

bserdar commented 6 years ago

It's the one you define the login form using a json arg via -F. I wonder if this works with your okta setup. The below setup works for keycloak. Once you do this, 'took token' simply asks for the password and prints out the token, no URLs to copy/paste.

took add oidc -n myapi -s 123 -b http://callback -c abc -u https://myserver \
 -F '{"id":"kc-form-login","usernameField":"username","passwordField":"password","fields":[{"input":"username","prompt":"User name"},\
    {"input":"password","prompt":"Password","password":true}]}'