I blogged previously about how you get the RPUrl field in the wctx field to see the originator of the message.
Normally for a .NET application, you'll see:
wctx: RPUrl=https://domain/application...
However, for SharePoint, you configure two identifiers in ADFS i.e.
https://domain/application/_trust/
urn:sharepoint:application
ADFS uses the urn in the RPUrl, so you'll see:
wctx: RPUrl=urn:sharepoint:application...
Which is a pain if you have to support both.
Enjoy!
Ideas and thoughts about Microsoft Identity, C# development, cabbages and kings and random flotsam on the incoming tide
Thursday, February 19, 2015
Tuesday, February 10, 2015
IIS : Application pool service account
IIS web sites run under application pools and if you look under "Advanced settings" you see an application pool runs under an Identity.
This Identity can be a number of accounts e.g. ApplicationPoolIdentity or NetworkService. But you can also set your own service account under "Custom account".
I needed to do this but kept getting:
"The specified password is invalid.Type a new password."
WTF?
Had a conversation with Mr. Google. Seriously - about the only probable cause not mentioned was the proverbial kitchen sink!
Then I realised that this was a domain account so I needed to type:
domain\account
Bang! Problem solved - sometimes we keep getting confused by all the trees.
Enjoy!
This Identity can be a number of accounts e.g. ApplicationPoolIdentity or NetworkService. But you can also set your own service account under "Custom account".
I needed to do this but kept getting:
"The specified password is invalid.Type a new password."
WTF?
Had a conversation with Mr. Google. Seriously - about the only probable cause not mentioned was the proverbial kitchen sink!
Then I realised that this was a domain account so I needed to type:
domain\account
Bang! Problem solved - sometimes we keep getting confused by all the trees.
Enjoy!
Thursday, February 05, 2015
ADFS : Claims are URI
Answered this question over on the forum.
But for general interest.
Claims are URI and URL are a subset of URI so you would expect that URI look something like:
http://domain/site
So you can't have a claim type of givenName.
To repeat:
Mapping Given-Name to givenName gives:
System.ArgumentException: ID4216: The ClaimType 'givenName' must be of format 'namespace'/'name'.
Mapping Given-Name to http://givenName gives:
MSIS7012: An error occurred while processing the request. Contact your administrator for details. ---> System.ArgumentException: ID4213: Cannot parse the ClaimType 'http://givenName' into a constituent name and namespace.
Mapping Given-Name to http://company.com/givenName works.
Which makes sense - you can't have a website with a URL of e.g. givenName.
Enjoy!
But for general interest.
Claims are URI and URL are a subset of URI so you would expect that URI look something like:
http://domain/site
So you can't have a claim type of givenName.
To repeat:
Mapping Given-Name to givenName gives:
System.ArgumentException: ID4216: The ClaimType 'givenName' must be of format 'namespace'/'name'.
Mapping Given-Name to http://givenName gives:
MSIS7012: An error occurred while processing the request. Contact your administrator for details. ---> System.ArgumentException: ID4213: Cannot parse the ClaimType 'http://givenName' into a constituent name and namespace.
Mapping Given-Name to http://company.com/givenName works.
Which makes sense - you can't have a website with a URL of e.g. givenName.
Enjoy!
Wednesday, February 04, 2015
ADFS : What happened to my roles?
Setting up a RP trust with the standard LDAP rule which maps "Token Groups - Unqualified Names" to Roles.
But when I enumerated the claims after RP authentication, some were missing?
WTF? when I do an AD memberOf, it displays them all?
Much head-scratching and investigation and then I remembered that for this ADFS claims rule only non-local domain security groups are returned.
You can confirm this in ADUC by clicking on the Properties / General tab and looking at the group scope and type.
But what if you are not Domain Admin?
Allow me to recommend AD Explorer.
Tip - just click OK on the first page (don't enter credentials) and it will "find" the default DC.
Then navigate to the security group.
Under the attributes, look for groupType.
It will be something like -2147483646.
As per AD Attributes, this is a Global group.
But my missing Security group displayed -2147483644 which is Domain Local.
Enjoy!
But when I enumerated the claims after RP authentication, some were missing?
WTF? when I do an AD memberOf, it displays them all?
Much head-scratching and investigation and then I remembered that for this ADFS claims rule only non-local domain security groups are returned.
You can confirm this in ADUC by clicking on the Properties / General tab and looking at the group scope and type.
But what if you are not Domain Admin?
Allow me to recommend AD Explorer.
Tip - just click OK on the first page (don't enter credentials) and it will "find" the default DC.
Then navigate to the security group.
Under the attributes, look for groupType.
It will be something like -2147483646.
As per AD Attributes, this is a Global group.
But my missing Security group displayed -2147483644 which is Domain Local.
Enjoy!
Tuesday, January 27, 2015
ADFS : ADFS 3.0 and OAuth2 Links
Gathering some links:
This is for Server 2012 R2.
Securing a Web API with Windows Server 2012 R2 ADFS and Katana
Specifically the section around configuring ADFS with "Add-ADFSClient" and the RP configuration.
OAuth 2 Authorization Code grant in ADFS
And my contribution:
ADFS : ADFS 3.0 and OAuth2
Enjoy!
This is for Server 2012 R2.
Securing a Web API with Windows Server 2012 R2 ADFS and Katana
Specifically the section around configuring ADFS with "Add-ADFSClient" and the RP configuration.
OAuth 2 Authorization Code grant in ADFS
And my contribution:
ADFS : ADFS 3.0 and OAuth2
Enjoy!
Tuesday, January 20, 2015
ADFS : ADFS 3.0 and OAuth2
This is for Server 2012 R2.
There are a lot of blogs about this but very little useful information.
So I thought about creating a client that shows this.
And then I thought about Authorization Server.
You can get this working if you want - just hook up to AS to ADFS as a normal ASP.NET RP for authentication.
But that's not what this post is about - I wanted to use the sample code to access ADFS.
Under "samples/Flows/Clients/OAuth2 CodeFlow you'll find the sample.
First you have to configure ADFS and you have to use PowerShell to do this - there's no wizard support.
You use the AdfsClient commands as per AD FS Cmdlets in Windows PowerShell.
Vittorio has blogged on this: Securing a Web API with Windows Server 2012 R2 ADFS and Katana.
Of interest is setting up the RP (worth repeating that it is neither WS-Fed nor SAML so don't tick any boxes) and the Add-AdfsClient command.
My RP then looks like:
So running Get-AdfsClient on my box:
ToDo: Code changes to the sample.
Enjoy!
There are a lot of blogs about this but very little useful information.
So I thought about creating a client that shows this.
And then I thought about Authorization Server.
You can get this working if you want - just hook up to AS to ADFS as a normal ASP.NET RP for authentication.
But that's not what this post is about - I wanted to use the sample code to access ADFS.
Under "samples/Flows/Clients/OAuth2 CodeFlow you'll find the sample.
First you have to configure ADFS and you have to use PowerShell to do this - there's no wizard support.
You use the AdfsClient commands as per AD FS Cmdlets in Windows PowerShell.
Vittorio has blogged on this: Securing a Web API with Windows Server 2012 R2 ADFS and Katana.
Of interest is setting up the RP (worth repeating that it is neither WS-Fed nor SAML so don't tick any boxes) and the Add-AdfsClient command.
My RP then looks like:
So running Get-AdfsClient on my box:
RedirectUri : {https://xxx/CodeFlow/callback}
Name : AMCodeFlowClient
Description : AM Code Flow Client
ClientId : codeclient
BuiltIn : False
Enabled : True
ClientType : Public
ToDo: Code changes to the sample.
Enjoy!
DOS : long file names
There are times when long file names are a pain.
I had a batch file that called a file inside a directory and the directory had spaces in the name e.g.
c:\a long name\another long name\program.exe
And it wouldn't damn well find it. Kept getting error messages like "File x ...".
I used "" and everything else I could think of.
Then from a long-distant past, I remembered DOS and the command
dir /x
This displays the short names generated for non-8dot3 file names.
So e.g. C:\Program Files\Resource Kit becomes C:\PROGRA~1\RESOUR~1
Putting the short name in the batch file solved the problem.
Go figure.
Enjoy!
I had a batch file that called a file inside a directory and the directory had spaces in the name e.g.
c:\a long name\another long name\program.exe
And it wouldn't damn well find it. Kept getting error messages like "File x ...".
I used "" and everything else I could think of.
Then from a long-distant past, I remembered DOS and the command
dir /x
This displays the short names generated for non-8dot3 file names.
So e.g. C:\Program Files\Resource Kit becomes C:\PROGRA~1\RESOUR~1
Putting the short name in the batch file solved the problem.
Go figure.
Enjoy!
Tuesday, January 06, 2015
Visual Studio : Missing dll
So there I am - back to work in 2015 and rebuilding a MVC project which I haven't touched for a while and bang - error after error after ...
WTF - Happy New Year!
A long conversation with Mr. Google and:
Errors like:
Could not load file or assembly 'file:///C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web Tools\Publish\Microsoft.VisualStudio.Web.Publish.dll' or one of its dependencies. The system cannot find the file specified.
and
Could not load file or assembly 'file:///C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web Tools\Scaffolding\Microsoft.AspNet.Scaffolding.VSExtension.12.0.dll' or one of its dependencies. The system cannot find the file specified.
and
Could not load file or assembly 'file:///C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web Tools\Languages\Microsoft.VisualStudio.JavaScript.Web.Extensions.dll' or one of its dependencies. The system cannot find the file specified.
etc.
This is related to VS 2013 Update 4 with ancillary suspects the Azure SDK 2.5 and O365 API Tools.
The solution is to repair VS 2013 Update 4.
I have Windows 7 so:
Control Panel - Programs and Features - Installed Updates - Visual Studio 2013 Update 4 (KB2829760) - Repair.
Just take a looong break while it's running.
Enjoy!
WTF - Happy New Year!
A long conversation with Mr. Google and:
Errors like:
Could not load file or assembly 'file:///C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web Tools\Publish\Microsoft.VisualStudio.Web.Publish.dll' or one of its dependencies. The system cannot find the file specified.
and
Could not load file or assembly 'file:///C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web Tools\Scaffolding\Microsoft.AspNet.Scaffolding.VSExtension.12.0.dll' or one of its dependencies. The system cannot find the file specified.
and
Could not load file or assembly 'file:///C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web Tools\Languages\Microsoft.VisualStudio.JavaScript.Web.Extensions.dll' or one of its dependencies. The system cannot find the file specified.
etc.
This is related to VS 2013 Update 4 with ancillary suspects the Azure SDK 2.5 and O365 API Tools.
The solution is to repair VS 2013 Update 4.
I have Windows 7 so:
Control Panel - Programs and Features - Installed Updates - Visual Studio 2013 Update 4 (KB2829760) - Repair.
Just take a looong break while it's running.
Enjoy!
Friday, December 19, 2014
ADFS : ADFS 3.0 and OpenID Connect / OAuth 2
This is for Server 2012 R2 and the documentation (to be polite) is somewhat lacking!
Came across a really neat tool for testing:
authnauthz
Also, Vittorio blogged some useful information:
Securing a Web API with Windows Server 2012 R2 ADFS and Katana
So let's put the pieces together.
In ADFS, create a RP as per Vittorio's instructions.
There's no certificate and no endpoints because you don't pick either SAML or WS-Fed.
Unlike my usual RP stuff, the identifier is not a URI.
I made the name and identifier simply "OAuth Test".
Then again following Vittorio,
So off to the test tool.
Under OAuth click "OIDC Authentication Request".
The authorisation endpoint is:
https://your adfs/adfs/oauth2/authorize
Response type: Ensure only code is ticked.
ADFS doesn't support anything else.
Set Resource to "OAuth Test"
Remove all Scope.
ADFS doesn't support any.
Click "Submit".
Off to ADFS, authenticate as per usual and you'll be be redirected to the Response page in the tool with an authorisation code.
Enjoy!
Came across a really neat tool for testing:
authnauthz
Also, Vittorio blogged some useful information:
Securing a Web API with Windows Server 2012 R2 ADFS and Katana
So let's put the pieces together.
In ADFS, create a RP as per Vittorio's instructions.
There's no certificate and no endpoints because you don't pick either SAML or WS-Fed.
Unlike my usual RP stuff, the identifier is not a URI.
I made the name and identifier simply "OAuth Test".
Then again following Vittorio,
Add-AdfsClient -Name "OAuth Test" -ClientId "112e0117-ef3d-44c4-a367-5b4bef313d8f" -RedirectUri "https://www.authnauthz.com/oauth/inboundauthenticationresponse" -Description "OAuth client"The ClientID and RedirectURL are from the test tool.
So off to the test tool.
Under OAuth click "OIDC Authentication Request".
The authorisation endpoint is:
https://your adfs/adfs/oauth2/authorize
Response type: Ensure only code is ticked.
ADFS doesn't support anything else.
Set Resource to "OAuth Test"
Remove all Scope.
ADFS doesn't support any.
Click "Submit".
Off to ADFS, authenticate as per usual and you'll be be redirected to the Response page in the tool with an authorisation code.
Enjoy!
Friday, December 05, 2014
ADFS : problems with Issuance Authorization Rules
These rules are useful if you want to allow or deny access to an application based on whether the authenticated user has a particular claim or not.
So I had a situation where there was a workflow involved and a user could not have access until they had been validated by an administrator.
So I created a claim called:
(Remember, these are URI not URL!).
Then in the Issuance Transform Rules tab, I had the normal LDAP rule to create the claim from an AD attribute and in the Issuance Authorization Rules tab I had a rule that said that if that claim had a value of "True" than allow access. I deleted the default "Allow access to anyone" rule.
Problem was - it didn't work?
Had a chat with Mr. Google (and it was a long chat!) and eventually figured out that each tab stands on its own i.e. there is no cross-pollination between them. The fact that you have a rule in one tab means nothing in another.
You have to repeat the rules in each tab.
Then all was sweetness and light!
Enjoy!
So I had a situation where there was a workflow involved and a user could not have access until they had been validated by an administrator.
So I created a claim called:
"http://company.com/claims/Validated"
(Remember, these are URI not URL!).
Then in the Issuance Transform Rules tab, I had the normal LDAP rule to create the claim from an AD attribute and in the Issuance Authorization Rules tab I had a rule that said that if that claim had a value of "True" than allow access. I deleted the default "Allow access to anyone" rule.
Problem was - it didn't work?
Had a chat with Mr. Google (and it was a long chat!) and eventually figured out that each tab stands on its own i.e. there is no cross-pollination between them. The fact that you have a rule in one tab means nothing in another.
You have to repeat the rules in each tab.
Then all was sweetness and light!
Enjoy!
Tuesday, December 02, 2014
IIS : You can ping the box but can't connect to IIS
Had the problem recently.
Laptop all running smoothly - could ping it no problem and connect to it via \\name.
But no way could I http to a website on the laptop.
Did the "ipconfig /flushdns" dance - no joy.
Double-checked all the IIS settings.
Had a chat with Mr. Google and found a suggestion to:
This tests if port 80 is open.
No joy - aha - so it's not IIS per se - it's the TCP/IP traffic on port 80.
Run up Windows Firewall. Yup - HTTP traffic on WWW was disabled for port 80. Allowed that - bingo - all A-OK.
Enjoy!
Laptop all running smoothly - could ping it no problem and connect to it via \\name.
But no way could I http to a website on the laptop.
Did the "ipconfig /flushdns" dance - no joy.
Double-checked all the IIS settings.
Had a chat with Mr. Google and found a suggestion to:
telnet "IP address" 80
This tests if port 80 is open.
No joy - aha - so it's not IIS per se - it's the TCP/IP traffic on port 80.
Run up Windows Firewall. Yup - HTTP traffic on WWW was disabled for port 80. Allowed that - bingo - all A-OK.
Enjoy!
Monday, November 17, 2014
ADFS : Using an AD primary key
There's a common use case where you are using some external system e.g. Facebook to authenticate and ADFS is in the pipeline as a R-STS.
Facebook only returns a GUID which doesn't mean a lot to AD so you have a registration flow where you ask the user for their details e.g. name, email address .. and then map the GUID to this.
So the next time the user logs in you have the GUID but need to use this as a "primary key" to get the rest of the details from AD.
Assume you have placed the Facebook GUID in a claim type called:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid
and it's stored in AD in extensionAttribute1.
So you have a normal LDAP claims rule that maps:
extensionAttribute1 --> http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid
Then you need a custom ADFS claim rule to do the extraction based on the mapping:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone"), query = "(&(extensionAttribute1={0})(objectClass=user));givenName,sn,mail,mobile;domain\user", param = c.Value);
So the rule searches AD for the user whose extensionAttribute1 value matches "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid" and then returns:
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone"
as four separate claims.
Enjoy!
Facebook only returns a GUID which doesn't mean a lot to AD so you have a registration flow where you ask the user for their details e.g. name, email address .. and then map the GUID to this.
So the next time the user logs in you have the GUID but need to use this as a "primary key" to get the rest of the details from AD.
Assume you have placed the Facebook GUID in a claim type called:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid
and it's stored in AD in extensionAttribute1.
So you have a normal LDAP claims rule that maps:
extensionAttribute1 --> http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid
Then you need a custom ADFS claim rule to do the extraction based on the mapping:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone"), query = "(&(extensionAttribute1={0})(objectClass=user));givenName,sn,mail,mobile;domain\user", param = c.Value);
So the rule searches AD for the user whose extensionAttribute1 value matches "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/guid" and then returns:
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone"
as four separate claims.
Enjoy!
Subscribe to:
Posts (Atom)
