IdentityServer / IdentityServer3

OpenID Connect Provider and OAuth 2.0 Authorization Server Framework for ASP.NET 4.x/Katana
https://identityserver.github.io/Documentation/
Apache License 2.0
2.01k stars 764 forks source link

Security of implicit client #1392

Closed rdzidziguri closed 9 years ago

rdzidziguri commented 9 years ago

Today we had a very strange question from one of our clients telling us about violation of security rules with our STS. we where told that, they use our thinktecture identity server and implicit flow, but they do not need ClientSecret after they authenticate they say that return URL contains information about claims which are sensitif so they asced to use implicit flow and secret key to encrypt this token they also sad that id_token is encrypted with RSA256 and after they decrypt it they are able to read all client related information. this seems to be strange for us here is the redirect url generated after redirecting client to their page.

http://company.domain.com/authorization.php#id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjB4ZmQzbk1tbGlieG5yblcwYlo2bFFEUnhHZyIsImtpZCI6IjB4ZmQzbk1tbGlieG5yblcwYlo2bFFEUnhHZyJ9.eyJub25jZSI6InNhZDMyMzVrMjAiLCJpYXQiOjE0MzIyMTkyODIsInN1YiI6IjI2IiwiYW1yIjoicGFzc3dvcmQiLCJhdXRoX3RpbWUiOjE0MzIyMDcwNDMsImlkcCI6Imlkc3J2IiwiYmFua19jbGllbnRJZCI6IjExODE2NTciLCJwZXJzb25hbF9udW1iZXIiOiIwMTAwNTAwNjE4MSIsImZpcnN0X25hbWUiOiLhg6Dhg5Dhg6Lhg5giLCJsYXN0X25hbWUiOiLhg6vhg5jhg6vhg5jhg5Lhg6Phg6Dhg5giLCJiaXJ0aF9kYXRlIjoiMTAvNy8xOTg1IiwiZW1haWwiOiJyLmR6aWR6aWd1cmlAdnRiLmdlIiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi52dGIuZ2UiLCJhdWQiOiJEQ0IwRDFFM0YzREYiLCJleHAiOjE0MzIyMTk1ODIsIm5iZiI6MTQzMjIxOTI4Mn0.IIIPI3J8UjrbocQ2IS96V-ySWJioad0FRgejXIFqxYHUNRm3YCkf00a3nXUliTZs7fJz7rnXsAKmTUZEHH4Im1QnX7vFAPS1hLDScASWOkRQXin3hTSiFLueV3qmt_yi6K6iGEovPQiJEyWPnMCip-p6pq8yYnyGu32DSMa_5lPiZrHra4W5ebi5hD2OXBMwtjcMa9IJdIp4_0Ftj1h_SExj7Hgcs7GIZTJ5eN2e4Ibu_oTgsKF977HU5Lr4ATC1mM1UxmpqG90bFthy9lcMLlBXmOqJ0fnMaKXre226-VRGWERqwdszn_b8IGXaRHNK5oXERMBC3BY17IvQLX8bO6Q9n6x-14ITGPqOTr9PaH3LH3ezknJ4nQOvAUZhZ6g72jwukqr5Qq9JM2vLSmArQgLs3wtO8OIJ8ej6ye3AP5SrqtRFUGOlh9Ppv281tuJa3Z5384-dsmOhpKKfUqbiOefEoR2phJ66RH6JrssO2rR0KtWClpVeobD05UBwfvgKE110c2MvZpoRxE17gN6qWHPKq7ZHvaoGhnmQeWc-zlvnJ8GFUcuNADEfSlEva03GsBNOVrQWpdhEaxsQkNix2CIzqwR1BtSldR4a4Rz8bCk_ldwzz_EBMb1t8AzNGzlyWZkBJy99lL5AT0p6SBGXNdUreZmVr1JukJKA4XbCXSI&scope=openid%20email%20profile_full&session_state=e0AXStEHePWYSzb5gbXrsh3uBpMAGJg4D-JNz9BsRds.a30ca8672147525cd311c7c4eaafefdb

and here is the URL they use to redirect clients for authentication

https://oursts.domain.com/connect/authorize?response_type=id_token&client_id=DCB0D1E3F3DF&redirect_uri=http://vpn.geopaysoft.com/vtb/1.php?&scope=openid%20email%20profile_full&nonce=sad3235kj

I think they are missing something out but even if they are wrong we Identity server exposes those information in public URL in a open way?

rdzidziguri commented 9 years ago

O and here is how my client is configured

                 new Client
                {
                    Enabled = true,
                    ClientName = "clientname",
                    ClientId = "DCB0D1E3F3DF",
                    ClientSecrets = new List<ClientSecret>()
                    {
                        new ClientSecret("somesecretkeyoftheclient".Sha256())
                    },
                    Flow = Flows.Implicit,
                    RequireConsent = false,

                    RedirectUris = new List<string>
                    {
                        "http://localhost:6841",
                        "https://localhost:44303",
                        "http://company.domain.com",
                        "http://company.domain.com/authorize.php"
                    }
                }
''''
jawadatgithub commented 9 years ago

if i understood correctly:

  1. everything after the hash fragment # stays in browser, so need worry about it (e.g., refere Uri won't include what's after #).
  2. using https with proper TLS config means the channel secure and 3rd party can't sniff the communication.
  3. in implicit flow usually u don't need client secret. client secret mandatory (in IdS3) for any flow that need to communicate with token endpoint.
rdzidziguri commented 9 years ago

Ok but even if redirec URL is not HTTPS here is what I get when we tried to redirect client to our local endpoint using ASP.NET Identity OWIN ''' https://localhost:44300/connect/authorize?client_id=DCB0D1E3F3DF&redirect_uri=https%3a%2f%2flocalhost%3a44303&response_mode=form_post&response_type=code&scope=openid+email+profile_full&state=OpenIdConnect.AuthenticationProperties%3dKaIIGOdCRECwyazRRI2S3wMP_s34YNHK2lEnorjAMPQk6SOR9o4E0Dy-n2GYnPYCTLi2UWXr48WWI2fEPJuGml1HBFtT0BQYY40Oa8SgitxvIuTa45EAzJ3weXSdpAVXuHS3g26VntXYSr3qdSgJQea8RtmDnEnfhBcKYlW0ATnUKSbkgQQT_B-2OyIMEIQgcfpNg6kaUkLs5cOJazFUwQ&nonce=635678353033740807.OGViYmVkNTEtMmY2Yi00MzNiLThmMTYtYTJlODM4OWJkOTdlZTgwZDUyZjQtYWZjNy00YTZhLWIxZDUtM2E0ZDNlMTFhZGNi '''

rdzidziguri commented 9 years ago

as far as I know they are using PHP maybe they are not using formpost? even if they where doing this it is not secured because anyone could see theyr redirect url and change that later in HTML

jawadatgithub commented 9 years ago

In Implicit flow the redirect URI used to verify the client identity (Requests tokens without explicit client authentication). means the client is public/untrusted.

the link you shared is https and response_type=code!! I don't understand how its related!

rdzidziguri commented 9 years ago

which link uses code second one uses Id-Token not Code? maybe I am missing something out there Event if client is public untrusted we do not want to expose user profile related information in the way our clients send us redirec URL how could they achieve that callback id_oken which includs all the information about user?

jawadatgithub commented 9 years ago

I meant your link here represent code flow! how is it related?

to help you relax, if you go through OIDC+OAuth2 specs: you will find that IdS3 follow that sharply. so doubting IdS3 is kinda doubting the standards. also IdentityServer3 is officially certified. http://openid.net/certification/

:)

rdzidziguri commented 9 years ago

:) nice to hear that All i want to know is how to prevent return url to contain all client claims and profile related info when inside id_token when flow type is implicit?

jawadatgithub commented 9 years ago

hmm, you can control what scopes to request, also if you don't need id_token then don't requested. in the client config: use ScopeRestrictions parameter.

edit: example

ScopeRestrictions = new List<string>
                    {
                        Constants.StandardScopes.OpenId,
                        "read",
                    },
rdzidziguri commented 9 years ago

but with Idsrv3 id_scope needs to be there isnot it true? all other scopes are optional as far as I know and if I do not request id_token after we authenticate user and redirect it back to the client application how client can get xtra information about client?

jawadatgithub commented 9 years ago

if you check clients samples: implicitclient-simple: you notice it work without requesting id_token. if later on you need access user info, then hit user info endpoint with the retrieved access-token, see docs.

rdzidziguri commented 9 years ago

Could you provide link on which client you are talking about? because id_token seems to be minimum response type one needs to set

jawadatgithub commented 9 years ago

https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/JavaScriptImplicitClient-Simple/index.html#L44-L49

jawadatgithub commented 9 years ago

I suspect you are confused with user info endpoint requirements:

http://identityserver.github.io/Documentation/docs/endpoints/userinfo.html

It requires a valid access token with at least the 'openid' scope.

rdzidziguri commented 9 years ago

Ok but within implicit flow I to not get any access_token at all

jawadatgithub commented 9 years ago
response_type = "token";

token is same access token.

rdzidziguri commented 9 years ago

Ok but thats not a correct format as id_token needs to be there always other way it will throw invalid request exception

rdzidziguri commented 9 years ago

What I think of all this after search all day is that even for implicit flow there must be some level of security so client profile related information can not be exposed easily. We are having very sensitive data related to our users so user profile needs to be received separately and this is number one priority for us. that's why I raised this issue from the very beginning even if client is public and not trusted is not this more reason to not to expose user claims as someone my just copy that URL decode bas64 data and get all the information about user..

jawadatgithub commented 9 years ago

As soon as a response type of token is requested, IdentityServer stops including the claims in the identity token. This is for optimization purposes, since you now have an access token that allows retrieving the claims from the userinfo endpoint and while keeping the identity token small.

source: http://identityserver.github.io/Documentation/docs/overview/mvcGettingStarted.html

in IdS3: implicit flow doesn't require Id_token to work. idtoken is OIDC spec, but I think IdS3 is backward compatible with vanilla OAuth2 (without OIDC addition). (this sentence need to be confirmed as I might misunderstood)_

jawadatgithub commented 9 years ago

To answer your last comment/conclusion:

  1. we need to remember the scope of the tools we use: OAuth2 and OpenID Connect standards designed to enable a third-party application to verify the identity of the End-User (Authentication) AND to obtain limited access (Authorization) to an HTTP service.
  2. based on point 1:

    expose user claims as someone my just copy that URL decode bas64 data and get all the information about user

you need to define who is that someone? is it limitation in OAuth2+OIDC specs or is it out of the context? for me it seems something related to DLP (data lose/leakage prevention).

anyway, after all this long discussion, I didn't get what's not secure in Implicit flow?

rdzidziguri commented 9 years ago

You are right DLP is the biggest issue here not because of authentication but of authorization. When I say someone I mean some 14 years old teenager siting in front of his laptop and copying that redirect URL extracting all the information about client and ... by the way I am talking about Commercial bank for which this solution was chosen as the best product for SSO implementation and it took me and my staff more than 3 month to prove that Thinktecture is the right solution for us so yeas DLP is real issue for as.

The only thing we have problem with is profile related information exposed via id_token and even if they use id_token token combination let I think the only solution here would be to indicate response_type=form_post doing this they will still get those parameters but using POST and POST combined with SSL might be ok

jawadatgithub commented 9 years ago

@leastprivilege please carry on with @rdzidziguri concerns.

as community member, I enjoyed this discussion.

leastprivilege commented 9 years ago

so back to your original question - yes you are right - the implicit flow does not require a client secret and is solely based on ownership of the domain of the return URL (hence the word implicit).

On the return URL there will be the requested tokens. None of them are encrypted and you define the contents of these tokens by configuring identityserver. They are only signed. This is all well understood. Check the specs and threat models.

But the user will only be able to see its own tokens - not the tokens of others users. To leak tokens to an untrusted return URL, the DNS resolution of the user's computer would need to be compromised.

If you need to hide identity information from the user it belongs to, then you can't use the user's computer to relay that information.

rdzidziguri commented 9 years ago

@leastprivilege I agree with you but Is not my assumptions right about providing response_mode=form_post while redirecting client for authentication? is this case even user will not be able to simply copy return URL decode id_token and access underlying user profile info.

What we recommended to our client was to First of all provide us HTTPS endpoint for redirection. Using response_mode=form_post. providing id_token token as a response_type. after redirection accessing profile endpoint for claims.

Even spec says if it is possible clients should support response_mode=form_post while passing id_token token as a response_type. IdSrv will stop exposing claims when redirecting authenticated user back to the client Using HTTPS with form post will provide them id_token and access_token so they can then request claims from profile endpoint.

Is this process flow decreasing security and DLP concerns of our client? Could you please correct thing I am wrong with.

leastprivilege commented 9 years ago

form_post is just another way of transmitting the token(s) back. They are are still transmitted via the client.

HTTPS is a pre-requisite ;)

id_token on its own will not let you access the userinfo endpoint. you need an access token for that.

brockallen commented 9 years ago

@rdzidziguri all set -- can we close this?

rdzidziguri commented 9 years ago

@brockallen Sure was really interesting conversation thank u all.