I'm hosting a WCF service in my resource server. Authorization seems to work fine. When I'm logging in my WCF service, I can get hold of the identity (aka user) who is being impersonated via the RequestContext.RequestMessage.Properties of the current OperationContext. I noticed that OAuthPrincipal only contains a property for AccessToken and nothing else. How do I get hold of the client identifier that is impersonating the user for the request?
In essence, I'd like to use that information to perform various tasks as part of the WCF service, like limiting how many requests the client can perform per second as well as track what operations the client is performing for both statistical reasons and security auditing.
If this is a simple omission, I'll file an issue in github.
The first thing you should know is that access tokens may be issued to anonymous clients. Then there are clients that have a client_id assigned but aren't actually authenticated, so there is no guarantee that the client is who it claims to be. If DNOA were to embed the client_id into the access token, it would only do so if the client had actually authenticated with the authorization server to obtain that access token, so sometimes the client_id would be empty.
The second thing to be aware of is that once the access token is issued, it (typically) is a bearer token, which means the client may share it with others (they shouldn't, but they *could*) who may then use it to send requests even though it's a different client.
The only real security that can be always relied on in the access token is the user who authorized it. Knowing the client_id is just gravy. Since your scenarios don't suggest the Resource Server is making security decisions based on the client_id (which is good!) I'd first suggest that you have your clients include their client_id in an HTTP header or the query string, and you then just know it is only an *alleged* client_id (not authenticated).
If you really need an authenticated client_id, then yes, embedding it in the access_token would probably be the right approach. I'm hesitant to just through it in there, even when it is authenticated, because the use of it by the resource server is often the sign of a faulty security model, IMO.
On Tuesday, March 27, 2012, Werner Strydom wrote: > Hello,
> I'm hosting a WCF service in my resource server. Authorization seems to > work fine. When I'm logging in my WCF service, I can get hold of the > identity (aka user) who is being impersonated via > the RequestContext.RequestMessage.Properties of the current > OperationContext. I noticed that OAuthPrincipal only contains a property > for AccessToken and nothing else. How do I get hold of the client > identifier that is impersonating the user for the request?
> In essence, I'd like to use that information to perform various tasks as > part of the WCF service, like limiting how many requests the client can > perform per second as well as track what operations the client is > performing for both statistical reasons and security auditing.
> If this is a simple omission, I'll file an issue in github.
> Thanks, > Werner
> -- > You received this message because you are subscribed to the Google Groups > "DotNetOpenAuth" group. > To view this discussion on the web visit > https://groups.google.com/d/msg/dotnetopenid/-/1e1rS8u7qTQJ. > To post to this group, send email to dotnetopenid@googlegroups.com<javascript:_e({}, 'cvml', 'dotnetopenid@googlegroups.com');> > . > To unsubscribe from this group, send email to > dotnetopenid+unsubscribe@googlegroups.com <javascript:_e({}, 'cvml', > 'dotnetopenid%2Bunsubscribe@googlegroups.com');>. > For more options, visit this group at > http://groups.google.com/group/dotnetopenid?hl=en.
-- -- Andrew Arnott "I [may] not agree with what you have to say, but I'll defend to the death your right to say it." - S. G. Tallentyre
You raise a number of good points. The system I'm working on requires all clients and users to be authenticated. About security in the Resource Server, I have a follow up question.
Suppose a client obtains an access token with a lifetime of 24h or longer from the authorization server. Soon after that (but before the access token expires), the user revokes the access of client due to some concern. Or perhaps, the user account is locked (for 10 minutes) due to a number of invalid logins. How should the resource server behave in this case? I'm asking because I may be missing something in the standard that can help mitigate the security risk here.
The only thing I can think of is to issue access tokens with a short lifetime, like 10 minutes. Other than that, the only other approach would be to perform a quick check whether the client revoked or whether user is locked.
> You raise a number of good points. The system I'm working on requires all > clients and users to be authenticated.
OK, then please file an issue for that then.
> About security in the Resource Server, I have a follow up question.
> Suppose a client obtains an access token with a lifetime of 24h or longer > from the authorization server. Soon after that (but before the access token > expires), the user revokes the access of client due to some concern. Or > perhaps, the user account is locked (for 10 minutes) due to a number of > invalid logins. How should the resource server behave in this case? I'm > asking because I may be missing something in the standard that can help > mitigate the security risk here.
> The only thing I can think of is to issue access tokens with a short > lifetime, like 10 minutes. Other than that, the only other approach would > be to perform a quick check whether the client revoked or whether user is > locked.
It's a good question. Short-lived access tokens are one mitigation. But in my favorite case of Twitter, imagine a user authorizes a client with their Twitter account, and the user realizes the client is spamming all their followers with ads at a high and continuing rate. The user immediately revokes authorization for that client. Even 10 minutes -- or even 1 more minute, can be potentially disastrous. Of course, if the clients are all authenticated, and if obtaining that client account requires some process and/or approval, the client may have an interest in *not* displeasing its users lest the authorization server revoke the client's account altogether. So this may not be a real issue in some settings. Each one is of course different.
But ultimately, if the Resource Server wants a *live* check as to the validity of the authorization, the RS must call the AS with the user-client-scope tuple (IAuthorizationServer.IsAuthorizationValid in DNOA parlance) to see if the access token represents an authorization that has not yet been canceled (for whatever reason). The OAuth2 spec does not specify how an RS->AS check such as this is to be performed, so it would be left as an exercise for the host to create such an endpoint at the AS. This wouldn't be a bad idea to build up support for within DNOA so that the AS endpoint for validating access tokens can be locked down to avoid 3rd parties using it to look up whether certain users have authorized certain apps, when it's none of their business. Please consider filing a ticket for this as well.
What about allowing the authorization server to populate a dictionary of arbitrary data or claims? It may then be up to the implementation of the authorization and resource server to include such information. This will also allow me to include information such as the tenant/realm the user belongs to.
I understand there are limits as to how much information we can pass in headers and it is a limitation I'm willing to accept.
Opening up the access token for arbitrary information certainly may be the way we eventually go, but I'd like to avoid it. With the exception of your emails, Werner, everybody that has asked for this feature wanted to pack info into the token that they were going to use in such a way as to open up security holes.
The user's tenant/realm info could arguably be put into the username (through some encoding with slash separators, for example) because it effectively creates a namespace for the user, which the resource server would then parse out. In fact, doing it this way may help prepare us for supporting (or altogether moving to) the "JWT" or "SWT" standards that describe a specific format for access tokens. I need to brush up on those (unfinalized) specs, but I don't *think* they allow arbitrary information.
-- Andrew Arnott "I [may] not agree with what you have to say, but I'll defend to the death your right to say it." - S. G. Tallentyre
On Tue, Mar 27, 2012 at 8:44 PM, Werner Strydom <bloudr...@gmail.com> wrote: > What about allowing the authorization server to populate a dictionary of > arbitrary data or claims? It may then be up to the implementation of the > authorization and resource server to include such information. This will > also allow me to include information such as the tenant/realm the user > belongs to.
> I understand there are limits as to how much information we can pass in > headers and it is a limitation I'm willing to accept.
> To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to > dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/dotnetopenid?hl=en.
> Opening up the access token for arbitrary information certainly may be the way we eventually go, but I'd like to avoid it. With the exception of your emails, Werner, everybody that has asked for this feature wanted to pack info into the token that they were going to use in such a way as to open up security holes.
> The user's tenant/realm info could arguably be put into the username (through some encoding with slash separators, for example) because it effectively creates a namespace for the user, which the resource server would then parse out. In fact, doing it this way may help prepare us for supporting (or altogether moving to) the "JWT" or "SWT" standards that describe a specific format for access tokens. I need to brush up on those (unfinalized) specs, but I don't think they allow arbitrary information.
> -- > Andrew Arnott > "I [may] not agree with what you have to say, but I'll defend to the death your right to say it." - S. G. Tallentyre
> On Tue, Mar 27, 2012 at 8:44 PM, Werner Strydom <bloudr...@gmail.com> wrote: > What about allowing the authorization server to populate a dictionary of arbitrary data or claims? It may then be up to the implementation of the authorization and resource server to include such information. This will also allow me to include information such as the tenant/realm the user belongs to.
> I understand there are limits as to how much information we can pass in headers and it is a limitation I'm willing to accept.
> To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/dotnetopenid?hl=en.
> -- > You received this message because you are subscribed to the Google Groups "DotNetOpenAuth" group. > To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/dotnetopenid?hl=en.
Can you elaborate as to what security holes may arise from passing additional data (aka claims) along as part of the access token? Assume we take the precaution to encrypt any sensitive data.
Generally, since OAuth2 specifies the information that comes into the token endpoint, and more or less what we know about the client during resource owner authorization, any additional information packed into the access token tends to be unrelated to what we have securely determined. For example, putting the client_id into the access token when the client wasn't actually authenticated may easily lead to the resource server misplacing confidence in that value. The RS may also use the client_id to customize its behavior and responses, which (I'd argue) should be based on other HTTP headers in order to keep the authorization uncoupled from behavior aside from strict security decisions.
Aside from the RS logging (strictly not security related) any additional information in the access token, what information can you imagine would be valuable to pack into it? I'd like to be exposed to more ideas here. :)
-- Andrew Arnott "I [may] not agree with what you have to say, but I'll defend to the death your right to say it." - S. G. Tallentyre
On Wed, Mar 28, 2012 at 5:20 PM, Werner Strydom <bloudr...@gmail.com> wrote: > Andrew,
> Can you elaborate as to what security holes may arise from passing > additional data (aka claims) along as part of the access token? Assume we > take the precaution to encrypt any sensitive data.
> To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to > dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/dotnetopenid?hl=en.
I'm approaching it from a slight different angle. Lets assume the resource and authorization servers are totally independent with their own databases web servers.
In a typical services orientated architecture, the authorization server may have certain domain knowledge such as
1. users 2. groups 3. groups users belong to 4. limiters (such as the storage people may use, whether they can perform certain actions or not)
When the access token is generated, the authorization server doesn't have enough knowledge to make a decision as that knowledge is maintained by resource servers. The resource server is responsible for serving the client while adhering to some limitations imposed by the account of the user the client is impersonating.
What is key to understand here is that authorization doesn't just imply that a user or client is valid and whether a client can gain access to resources at a resource server on behalf of the user. It also includes certain business rules as to how the client and/or user may use the resource server.
For example, a user may access a resource called "task" with id "1", provided that the user make no more than 10 requests a minute. If the user "upgrades" their account to "Premium", then the user can request no more than 100 tasks per minute.
There is no way one can trust the client to pass this sort of information as part of HTTP headers.
So this presents a couple of questions, namely:
1. should the authorization server pass such information to the resource server? 2. if the answer to 1 is "no", then what alternatives exist? 3. if the answer to 1 is "yes", then the answer is how?
My suggestion would be to make DotNetOpenAuth claims aware, support something similar to IClaimsPrincipal and IClaimsIdentity and serialize those claims in the access token.
An *excellent* argument, Werner. Consider the position won. :) Please file a ticket. -- Andrew Arnott "I [may] not agree with what you have to say, but I'll defend to the death your right to say it." - S. G. Tallentyre
On Wed, Mar 28, 2012 at 10:28 PM, Werner Strydom <bloudr...@gmail.com>wrote:
> I'm approaching it from a slight different angle. Lets assume the > resource and authorization servers are totally independent with their own > databases web servers.
> In a typical services orientated architecture, the authorization server > may have certain domain knowledge such as
> 1. users > 2. groups > 3. groups users belong to > 4. limiters (such as the storage people may use, whether they can > perform certain actions or not)
> When the access token is generated, the authorization server doesn't have > enough knowledge to make a decision as that knowledge is maintained by > resource servers. The resource server is responsible for serving the > client while adhering to some limitations imposed by the account of the > user the client is impersonating.
> What is key to understand here is that authorization doesn't just imply > that a user or client is valid and whether a client can gain access to > resources at a resource server on behalf of the user. It also includes > certain business rules as to how the client and/or user may use the > resource server.
> For example, a user may access a resource called "task" with id "1", > provided that the user make no more than 10 requests a minute. If the user > "upgrades" their account to "Premium", then the user can request no more > than 100 tasks per minute.
> There is no way one can trust the client to pass this sort of information > as part of HTTP headers.
> So this presents a couple of questions, namely:
> 1. should the authorization server pass such information to the > resource server? > 2. if the answer to 1 is "no", then what alternatives exist? > 3. if the answer to 1 is "yes", then the answer is how?
> My suggestion would be to make DotNetOpenAuth claims aware, support > something similar to IClaimsPrincipal and IClaimsIdentity and serialize > those claims in the access token.
> To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to > dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/dotnetopenid?hl=en.
I would argue that this falls under the scope of .. eh.. scope.
if (currentNumberOfCalls >100 && !user.hasScope('canmakemorethan100')) { trow new Exception('sorry champ');
}
As an aside to this, using scopes for everything will quickly lead to extremely big tokens, so Andrew, how do you feel about supporting a) the resource server and authorization server sharing a map of scopes so that you can use bitmapping to efficiently store these in the token b) hashing every scope down to, say 8 bytes ?
a is what I would go for, and I know this would alleviate some of the problems people are seing with self-describing tokens.
On Fri, Mar 30, 2012 at 6:21 AM, Andrew Arnott <andrewarn...@gmail.com>wrote:
> An *excellent* argument, Werner. Consider the position won. :) Please > file a ticket.
> -- > Andrew Arnott > "I [may] not agree with what you have to say, but I'll defend to the death > your right to say it." - S. G. Tallentyre
> On Wed, Mar 28, 2012 at 10:28 PM, Werner Strydom <bloudr...@gmail.com>wrote:
>> I'm approaching it from a slight different angle. Lets assume the >> resource and authorization servers are totally independent with their own >> databases web servers.
>> In a typical services orientated architecture, the authorization server >> may have certain domain knowledge such as
>> 1. users >> 2. groups >> 3. groups users belong to >> 4. limiters (such as the storage people may use, whether they can >> perform certain actions or not)
>> When the access token is generated, the authorization server doesn't have >> enough knowledge to make a decision as that knowledge is maintained by >> resource servers. The resource server is responsible for serving the >> client while adhering to some limitations imposed by the account of the >> user the client is impersonating.
>> What is key to understand here is that authorization doesn't just imply >> that a user or client is valid and whether a client can gain access to >> resources at a resource server on behalf of the user. It also includes >> certain business rules as to how the client and/or user may use the >> resource server.
>> For example, a user may access a resource called "task" with id "1", >> provided that the user make no more than 10 requests a minute. If the user >> "upgrades" their account to "Premium", then the user can request no more >> than 100 tasks per minute.
>> There is no way one can trust the client to pass this sort of information >> as part of HTTP headers.
>> So this presents a couple of questions, namely:
>> 1. should the authorization server pass such information to the >> resource server? >> 2. if the answer to 1 is "no", then what alternatives exist? >> 3. if the answer to 1 is "yes", then the answer is how?
>> My suggestion would be to make DotNetOpenAuth claims aware, support >> something similar to IClaimsPrincipal and IClaimsIdentity and serialize >> those claims in the access token.
>> To post to this group, send email to dotnetopenid@googlegroups.com. >> To unsubscribe from this group, send email to >> dotnetopenid+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/dotnetopenid?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "DotNetOpenAuth" group. > To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to > dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/dotnetopenid?hl=en.
If we were to overload scopes with additional information, say "storage2MB", then one has to consider that the client may see it (as per section 3.3 in the spec). Next time, the client may attempt to pass in "storage10MB" as a possible scope. On the server side the authorization server has to filter the scopes etc to prevent the client from obtaining more rights than they are really entitled to. Then there is the issue of confidential information that the authorization server needs to pass to the resource server. Additional precautions are needed to prevent the client from seeing it. One has to come up with a scheme to handle variable data. Perhaps in the form of "storage=20MB", but this may be challenging when some data requires encryption.
This seems rather problematic and cumbersome.
So I'm not in favor of using "scopes" for this but instead to another simple secure manner to send claims from the authorization server to the resource server as part of the access token.
I think both have good points here. As it is currently implemented (and I'm in favor of keeping it this way), DNOA *always* encrypts the access token so the client cannot read it. So the concern about scopes that the auth server adds being seen by the client wouldn't be an issue, as long as that encryption occurs. However, quotas don't sound like they're very amenable to scopes. I can see group memberships being added as scopes or additional claims, but I'm sufficiently convinced that claims and scopes don't totally overlap.
As for a "bitmap" of scopes to keep the scopes value shorter, that I consider an implementation detail between AS and RS. DNOA doesn't prescribe the format of scopes beyond the oauth2 spec. -- Andrew Arnott "I [may] not agree with what you have to say, but I'll defend to the death your right to say it." - S. G. Tallentyre
On Fri, Mar 30, 2012 at 12:36 PM, Werner Strydom <bloudr...@gmail.com>wrote:
> If we were to overload scopes with additional information, say > "storage2MB", then one has to consider that the client may see it (as per > section 3.3 in the spec). Next time, the client may attempt to pass in > "storage10MB" as a possible scope. On the server side the authorization > server has to filter the scopes etc to prevent the client from obtaining > more rights than they are really entitled to. Then there is the issue of > confidential information that the authorization server needs to pass to the > resource server. Additional precautions are needed to prevent the client > from seeing it. One has to come up with a scheme to handle variable data. > Perhaps in the form of "storage=20MB", but this may be challenging when > some data requires encryption.
> This seems rather problematic and cumbersome.
> So I'm not in favor of using "scopes" for this but instead to another > simple secure manner to send claims from the authorization server to the > resource server as part of the access token.
> To post to this group, send email to dotnetopenid@googlegroups.com. > To unsubscribe from this group, send email to > dotnetopenid+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/dotnetopenid?hl=en.