Service Bus: Operation-level Authorization
- How would one go about authorizing access to service operations on an operation-by operation level? For example, in role-based security you could demand a user is in a certain role at the method level. Obviously, the service bus and ACS use claims-based security. But the client application's claims are only visible to the service bus - it strips them before relaying the message to the service (as per the "Developer's Guide to the .NET Service Bus".
How then, might I learn anything about my client caller in the service code that would let me decide to let him invoke individual methods or not?
Any help would be greatly appreciated. Maybe I'm missing something obvious.
Tutte le risposte
- Hello, you can find a sample located in C:\Program Files (x86)\Microsoft .NET Services (Dec 2008 CTP) SDK\Samples\AccessControl\GettingStarted\UserNamePasswordCalculatorService. It will tell you how to check the user's authorization at the operation level. Essentially, you can check OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets to see if the user has the required claim by the operation. So within your operation, you can call the following DemandActionClaim method:
public static void DemandActionClaim(string claimValue)
{
foreach (ClaimSet claimSet in OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets)
{
foreach (Claim claim in claimSet)
{
if (AccessControlHelper.CheckClaim(claim.ClaimType, claim.Resource.ToString(), "http://docs.oasis-open.org/wsfed/authorization/200706/claims/action", claimValue))
{
if (AccessControlHelper.IsIssuedByIbn(claimSet))
{
return;
}
}
}
}
throw new FaultException("Access denied.");
}
static bool IsIssuedByIbn(ClaimSet claimSet)
{
foreach (Claim claim in claimSet.Issuer)
{
if (AccessControlHelper.CheckClaim(claim.ClaimType, claim.Resource.ToString(), "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns", "accesscontrol.windows.net"))
{
return true;
}
}
return false;
}
static bool CheckClaim(string claimType, string claimValue, string expectedClaimType, string expectedClaimValue)
{
if (StringComparer.OrdinalIgnoreCase.Equals(claimType, expectedClaimType) &&
StringComparer.OrdinalIgnoreCase.Equals(claimValue, expectedClaimValue))
{
return true;
}
return false;
}
Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights. - Hi, thanks for the reply.
What I'm wondering about is the operation level authorization across the Service Bus. I realize you can check the claim set programmatically when using ACS for auth to normal services - but the problem is that when a client calls through the Service Bus to my service, the service bus strips the claimsets - so if you check OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets in a service bus service the count will always be 0.
Why does the service bus not pass through client claim sets to the receiving service... and how can we go about operation level authorization for service bus services?
Thanks - Have you setup your rules in ACS? Please follow those steps:
- Go to https://accesscontrol.ex.azure.microsoft.com/GettingStarted.aspx, and click the Advanced Button.
- Add a new scope if you don't have any. Click the scope link to open the Rules page.
- Add a new rule. The input claim type can be Group, since you're using role based authorization.
- The output claim type should be Action. Enter a meaningful value for the output claim based on your service operation. For example, ViewFiles.
- Add more rules if required.
- Now you can pass "ViewFiles" to the DemandActionClaim method.
Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights. - Hi,
Perhaps I can restate the issue to be more clear.
The issue is that the Service Bus removes the client's token from the message before relaying the message to the receiver. This is clearly stated in this document: http://www.microsoft.com/downloads/info.aspx?na=46&p=3&SrcDisplayLang=en&SrcCategoryId=&SrcFamilyId=5057e2b3-c8e5-4b26-a601-ff9621589ce3&u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2f9%2f0%2fA%2f90AE8BDF-F611-4808-986B-43DC7C7D7B25%2fMicrosoft+.NET+Service+Bus.docx&oRef=http%3a%2f%2fwww.microsoft.com%2fdownloads%2fresults.aspx%3fNextOrPrevClause%3d2%7c%2b1647%26DisplayLang%3den%26freetext%3d.net%2bservices%26sortCriteria%3dpopularity%26sortOrder%3dascending%26nr%3d20
Can you please confirm whether or not authorization to services through the service bus is no more granular that per solution? Is this going to be changed in future versions? Any other insight would be appreciated.
Thanks,
Tony P
Avanade Corporation
Seattle, WA - Yes, the authorization token (SAML token) is removed. But the claims output by your rules are not removed. For example, if you have rule which outputs a claim: type: Group, value: MyGroup. You will be able to get it on the client side. Have you encountered any problems?
Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights.- Contrassegnato come rispostaYi-Lun LuoMSFT, Moderatoremercoledì 18 marzo 2009 10.27
- Contrassegno come risposta annullatotprudente lunedì 23 marzo 2009 18.08
- Hi, sorry for the delayed reply.
Yes, I am having problems. In the ACS portal, in the Service Bus scope, I have set up a rule which outputs a claim of Group=[MyGroupName] if the UserName=[MySolutionName].
Then in my service operation code, I have:
ReadOnlyCollection<System.IdentityModel.Claims.ClaimSet> set = OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets;
set.Count is always 0, regardless of the rules I set up in the ACS portal for the service bus scope. Am I missing something?
Regards,
Tony This should work. Possibly there're some problems in your configuration... I suggest you to run the calculator sample first. If you can get it work, you'll have an easier time to get your own application work. To get the sample work, you need to follow the readme.htm. Pay special attention to the following:
- At the "Add Application" page, enter "http://localhost/CalculatorService" in the Application URI text box
In your own solution, you must make sure your service is hosted at the address specified in the Application URI. In this sample, the service is hosted at http://localhost/CalculatorService.
- Find and Replace all occurrences of "replacewithsolutionname" with your solution name
You need to do the same in your own solution.
Also make sure the certificates (if you're using any) are correct.
Lante, shanaolanxing This posting is provided "AS IS" with no warranties, and confers no rights.Actually I don't feel the calculator example applies to this situation because it doesn't use the service bus. My service is not hosted at http://[...], it is hosted at sb://[...].
There is a built in scope (Application) in the access control service for the service bus, and I'm assuming that is where I would add claim rules for my service, which listens to the service bus, correct? Currently in this scope I have the required action=send and action=listen rules, plus an additional rule that does a custom claim type group=myGroup.
The service bus apparantly removes the claimsets from the request before sending it to the service. Can you confirm or deny that the service bus removes the claim sets before forwarding a request to a service?
Thanks,
TonyWell I have exactly the same problem, have you got the solution yet? Thanks a lot.

