Jorge's Quest For Knowledge!

All About Identity And Security On-Premises And In The Cloud – It's Just Like An Addiction, The More You Have, The More You Want To Have!

Archive for the ‘Active Directory Federation Services (ADFS)’ Category

(2019-05-25) Windows Hello For Business (WH4B) Bootstrapping

Posted by Jorge on 2019-05-25


A few months ago I configured and implemented Windows Hello For Business (WH4B) using the “Hybrid AAD Joined Certificate Trust”. I chose this method over the “Hybrid AAD Joined Key Trust” because we did not have W2K16 DCs yet and we did have an ADFS deployment. This choice was really easy due to the lack of W2K16 DCs, otherwise we most likely would have chosen “Hybrid AAD Joined Key Trust” over “Hybrid AAD Joined Certificate Trust”.

Before going all crazy, we decided to start easy and implement it on a very limited scale scoped to specific Windows 10 computers and specific users. We created a small list of users (less than 10) and that list contained users logging on through username and password and users logging on through smartcard and pin.

To be able to implement this, we had to satisfy the following prerequisites:

  • AAD subscription
  • AD
    • W2K8R2 DCs or higher (+DFL/FFL)
    • W2K16 AD schema
    • Configuration to support Hybrid Azure AD Domain Join
    • Security group to scope computers and permission computer based GPO
    • Security group to scope usersand permission user based GPO

  • PKI infrastructure running on W2K12 or higher as trust anchor
    • Certificate Template to issue Kerberos AuthN certificate for DCs through auto enrolment (and therefore correct permissioning!)
    • Certificate Template to issue Registration Authority certificate for ADFS through auto enrolment (and therefore correct permissioning!)
    • Certificate Template to issue WH4B AuthN certificate for clients by ADFS through auto enrolment  (and therefore correct permissioning!)
    • DCs need certificate to be trusted by clients
    • Users need authentication certificates distributed through ADFS registration authority (RA)
    • Certificate Templates need to be configured with at least W2K12 or higher certificate authority support to be able to configure the correct provider and algorithm in the cryptography TAB

  • AAD Connect, no DirSync and no AAD Sync
    • Configuration to support Hybrid Azure AD Domain Join
    • Device writeback
      • To writeback the values in "msDS-KeyCredentialLink" on AD user account, RP/WP permissions are needed on that attribute. That can be done in a custom manner like assigning a custom group those permissions whereas that custom group may already have other permissions to read/write, or the AD connector account is added to the "KeyAdmins" group in AD

  • ADFS
    • Configuration to support Hybrid Azure AD Domain Join
    • ADFS 2016 or higher as a registration authority
    • Device authentication enabled at global level
    • Configured as registration authority with the correct certificate templates for RA and WH4B

  • Enrolment through username/password AND some form of MFA (AAD MFA Cloud, ADFS with AAD MFA Cloud/On-prem, ADFS with 3rd party MFA, etc)
  • Windows 10 v1703 or higher
  • Win10 Devices joined to AD and AAD, a.k.a. Hybrid Azure AD Domain Joined

While everything was in place, we were good to go!

Users logging on with username and password should see the following screen:

image

Figure 1: Windows Hello For Business Initial Provisioning Screen After Logging On With Username And Password

Users logging on with smartcard and pin should also see the same screen right after logging on, but they did not. Damn!

Let the troubleshooting begin! Smile

After provisioning, looking at the PRTs through DSREGCMD /STATUS

SNAGHTML4235b5

Figure 2: SSO State: Azure AD PRT = YES And EnterprisePRT (ADFS PRT) = NO

image

Figure 3: NGC Prerequisite Check: No ADFS Refresh Token

OK, it is clear there is no ADFS PRT, which IS a requirement for WH4B, hence why it fails

On the client in the “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log you may notice the following error or similar with some correlation ID. Save the correlation ID somewhere as you will need that later!

image

Figure 4: Client Side: Error In The “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log

Http request status: 401. Method: POST Endpoint Uri: https://fs.iamtec.nl/adfs/oauth2/token/ Correlation ID: A9820E01-5D3A-4138-BCFF-72B454B67F1B

On the client in the “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log you may notice the following error or similar with no correlation ID and a small hint of where things might be wrong. Nevertheless, still not clear enough!

image

Figure 5: Client Side: Error In The “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log

OAuth response error: interaction_required
Error description: MSIS9699: GlobalAuthenticationPolicy on the Server doesn’t allow this OAuth JWT Bearer request. Please contact the administrator to update the GlobalAuthenticationPolicy.
CorrelationID:

On the client in the “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log you may notice the following error or similar with some correlation ID. If you look carefully, you will see it is the same correlation ID and in figure 4. Save the correlation ID somewhere as you will need that later, if you have not done that already!

image

Figure 6: Client Side: Error In The “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log

Enterprise STS Logon failure. Status: 0xC0000250 Correlation ID: A9820E01-5D3A-4138-BCFF-72B454B67F1B

In your face, no WH4B for you as authN against ADFS failed for some reason!

image

Figure 7: Client Side: Error In The “Applications And Services Log\Microsoft\Windows\User Device Registration\Admin” Event Log

Windows Hello for Business provisioning will not be launched.
Device is AAD joined ( AADJ or DJ++ ): Yes
User has logged on with AAD credentials: Yes
Windows Hello for Business policy is enabled: Yes
Windows Hello for Business post-logon provisioning is enabled: Yes
Local computer meets Windows hello for business hardware requirements: Yes
User is not connected to the machine via Remote Desktop: Yes
User certificate for on premise auth policy is enabled: Yes
Enterprise user logon certificate enrollment endpoint is ready: Yes
Enterprise user logon certificate template is : Yes
User has successfully authenticated to the enterprise STS: No
Certificate enrollment method: enrollment authority
See
https://go.microsoft.com/fwlink/?linkid=832647 for more details.

On the ADFS server you will most likely find events similar to the ones below. Look at the event with the same correlation ID. If you have multiple ADFS servers, either check all ADFS servers for events with the same correlation ID, or check some central SIEM solution, or use PowerShell to query all ADFS servers, or configure your client to point to one specific ADFS server by temporarily configuring the HOSTS file.

image

Figure 8: ADFS Server Side: Errors In The “Applications And Services Log\AD FS\Admin” Event Log

And there is the reason! Certificate Authentication is NOT enabled on the intranet for primary authN! What the heck. Did not expect this one. I would expect that Windows Authentication on the intranet as primary authN would be enough for this to work, Apparently it explicitly needs the authN method to be enabled that is being used at logon.

image

Figure 9: ADFS Server Side: Error In The “Applications And Services Log\AD FS\Admin” Event Log

Encountered error during OAuth token request.

Additional Data

Exception details:
Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthInteractionRequiredException: MSIS9462: Interaction is required by the token broker to resolve the issue. Enable CertificateAuthentication in the Global Policy.
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthJWTBearerRequestContext.ValidateAuthPolicy()
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthJWTBearerRequestContext.ValidateJWTBearer()
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthJWTBearerRequestContext.ValidateCore()

And there is the reason again! Certificate Authentication is NOT enabled on the intranet for primary authN!

image

Figure 10: ADFS Server Side: Error In The “Applications And Services Log\AD FS\Admin” Event Log

Encountered error during OAuth token request.

Additional Data

Exception details:
Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthInteractionRequiredException: MSIS9462: Interaction is required by the token broker to resolve the issue. Enable CertificateAuthentication in the Global Policy.
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthJWTBearerRequestContext.ValidateAuthPolicy()
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthJWTBearerRequestContext.ValidateJWTBearer()
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthJWTBearerRequestContext.ValidateCore()
   at Microsoft.IdentityServer.Web.Protocols.ProtocolContext.Validate()
   at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthTokenProtocolHandler.ProcessJWTBearerRequest(OAuthJWTBearerRequestContext jwtBearerContext)

It will not get more explicit than this! If all error were like this!

In this case when logging on with smartcard and pin and to be able to start WH4B provisioning, Certificate Based Authentication needs to be enabled at the INTRANET level in ADFS.

For that you can use the following PowerShell commands:

Get-AdfsGlobalAuthenticationPolicy
$currentListOfProvidersForPrimaryAuthNForIntranet = (Get-AdfsGlobalAuthenticationPolicy).PrimaryIntranetAuthenticationProvider
If ($currentListOfProvidersForPrimaryAuthNForIntranet -notcontains "CertificateAuthentication") {
    $newListOfProvidersForPrimaryAuthNForIntranet = $currentListOfProvidersForPrimaryAuthNForIntranet + "CertificateAuthentication"
    Set-AdfsGlobalAuthenticationPolicy -PrimaryIntranetAuthenticationProvider $newListOfProvidersForPrimaryAuthNForIntranet
}
Get-AdfsGlobalAuthenticationPolicy

image

Figure 11: Configuring The ADFS Global Authentication Policy – Providers For Primary Authentication For The Intranet

Now logging off and logging back on again, you should see the following screen:

image

Figure 12: Windows Hello For Business Initial Provisioning Screen After Logging On With Smartcard And PIN

PS: Look for differences when a user logs on with username and password!

After provisioning, looking at the PRTs through DSREGCMD /STATUS

image

Figure 13: SSO State: Azure AD PRT = YES And EnterprisePRT (ADFS PRT) = YES

image

Figure 14: NGC Prerequisite Check: No ADFS Refresh Token

At PRT level, everything is looking good now!

Enjoy and have fun!,

Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Advertisements

Posted in Active Directory Federation Services (ADFS), Certificate Based AuthN, WH4B, Windows Client | Leave a Comment »

(2019-05-22) Some Basic Steps For Troubleshooting PRTs

Posted by Jorge on 2019-05-22


In Windows 10 currently there are 2 PRTs:

  • The Azure AD Primary Refresh Token
  • And the Enterprise Primary Refresh Token, a.k.a. the ADFS Primary Refresh Token

For both the following troubleshooting steps apply if you are experiencing issues somehow:

  • Always check the output of: DSREGCMD.EXE /STATUS
  • Event Logs to check on the client:
    • “Applications And Services Log\Microsoft\Windows\AAD\Operation” Event Log
    • “Applications And Services Log\Microsoft\Windows\User Device Registration\Admin” Event Log
  • Any correlation ID in any event related to the error experienced on the client, can most like also be found at server side in the corresponding event log. If server side is AAD, then you need Microsoft. If server side is ADFS, then you can check it yourself
  • Changing or resetting the password, invalidates the current PRTs and fresh ones are retrieved/generated
  • If a PRT is missing, triggering to try to retrieve a PRT can be done by either logoff/logon or lock/unlock

With this information you should have a good start to try troubleshooting PRT related issues, although not always easy!

Do not forget to also read Jairo’s blog post about how SSO works in Windows 10

Enjoy and have fun!,

Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Azure AD PRT, Enterprise PRT, Windows Azure Active Directory | Leave a Comment »

(2019-03-06) Will WAP v3.0 Work With ADFS v4.0 Or Later?

Posted by Jorge on 2019-03-06


Will it work to have WAP v3.0 (WAP in Windows Server 2012 R2) in an ADFS v4.0 Farm (ADFS in Windows Server 2016) during an upgrade/migration scenario?

Yes, it will, even if you increase the ADFS Farm Level! There is a “BUT”, and that is it will depend on what you are using!

Some examples

If you are just publishing applications and doing your thing as you were with the ADFS v3.0 Farm, you are OK to go.   

image

Figure 1: WAP v3.0 Successfully Retrieving Its Config From An ADFS v4.0 Farm

The federation server proxy successfully retrieved its configuration from the Federation Service ‘FS.IAMTEC.NL’.

image

Figure 2: WAP v3.0 Successfully Added/Removed The Listed Endpoints

The AD FS proxy service made changes to the endpoints it is listening on based on the configuration it retrieved from the Federation Service.

Endpoints added:
https://+:443/FederationMetadata/2007-06/
https://+:443/adfs/ls/
https://+:49443/adfs/ls/
https://+:443/adfs/oauth2/token/
https://+:443/adfs/oauth2/logout/
https://+:443/adfs/oauth2/authorize/
https://+:49443/adfs/oauth2/authorize/
https://+:443/adfs/oauth2/devicecode/
https://+:443/adfs/oauth2/deviceauth/
https://+:443/adfs/.well-known/openid-configuration/
https://+:443/adfs/discovery/keys/
https://+:443/EnrollmentServer/
https://+:443/adfs/portal/
https://+:49443/adfs/portal/
https://+:443/adfs/portal/updatepassword/
https://+:443/adfs/userinfo/
https://+:443/adfs/services/trust/2005/windowstransport/
https://+:443/adfs/services/trust/2005/certificatemixed/
https://+:49443/adfs/services/trust/2005/certificatetransport/
https://+:443/adfs/services/trust/2005/usernamemixed/
https://+:443/adfs/services/trust/2005/issuedtokenmixedasymmetricbasic256/
https://+:443/adfs/services/trust/2005/issuedtokenmixedsymmetricbasic256/
https://+:443/adfs/services/trust/13/certificatemixed/
https://+:443/adfs/services/trust/13/usernamemixed/
https://+:443/adfs/services/trust/13/issuedtokenmixedasymmetricbasic256/
https://+:443/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256/
https://+:443/adfs/services/trust/mex/
 

Endpoints removed:

Remember though that ADFS v4.0 supports other endpoints. And that’s were the WAP v3.0 may not understand everything published by ADFS v4.0. For the following endpoint you will see the following error when WAP v3.0 retrieves its config from the ADFS v4.0 farm.

image

Figure 3: WAP v3.0 Fails To Add A Listener For A Specific Endpoint Published By ADFDS v4.0

AD FS proxy service failed to start a listener for the endpoint ‘Endpoint details:
     Prefix : /.well-known/webfinger
     PortType : HttpsDevicePort
     ClientCertificateQueryMode : None
     CertificateValidation : None
     AuthenticationSchemes : Anonymous
     ServicePath : /.well-known/webfinger
     ServicePortType : HttpsDevicePort
     SupportsNtlm : False

Exceptiondetails:
System.Net.HttpListenerException (0x80004005): Access is denied
   at System.Net.HttpListener.AddAllPrefixes()
   at System.Net.HttpListener.Start()
   at Microsoft.IdentityServer.WebHost.HttpListenerBase.Start(UInt32 contextPoolSize)
   at Microsoft.IdentityServer.ProxyService.ProxyHttpListener.Start()
   at Microsoft.IdentityServer.ProxyService.EndpointManager.ApplyConfiguration(ProxyEndpointConfiguration proxyEndpointConfiguration)

User action: Ensure that no conflicting SSL bindings are configured for the specified endpoint.

Now, a good way to make sure your WAP v3.0 stops functioning in an ADFS v4.0 farm, is to enable “Alternate Host Name Binding” as explanined in (2019-03-05) Certificate Based Authentication In ADFS (Legacy And New) – The Complete Information To Get This Working

As soon as you enable “Alternate Host Name Binding” you will see the following error when WAP v3.0 tries to retrieve its config from the ADFS v4.0 farm. Also pay attention to what it suggests you should do! Smile

image

Figure 4: WAP v3.0 Fails To Retrieve Its Config From The ADFS v4.0 Farm After Enabling Alternate Host Name Binding

Unable to retrieve proxy configuration data from the Federation Service.

Additional Data

Trust Certificate Thumbprint:
7EB5B6A48B7273468ECC5EB67E05E62DDD04D145

Status Code:
UpgradeRequired

Exception details:
System.Net.WebException: The remote server returned an error: (426) Upgrade Required.
   at System.Net.HttpWebRequest.GetResponse()
   at Microsoft.IdentityServer.Management.Proxy.StsConfigurationProvider.GetStsProxyConfiguration()

If you want to make your WAP v3.0 again in this scenario you really need to disable Alternate Host Name Binding!

So before enabling “Alternate Host Name Binding” make sure to upgrade your WAP v3.0 to the latest version, it deserves it!

To disable “Alternate Host Name Binding” and start using legacy mode again for Certificate Based AuthN, just execute the following command on one ADFS server:

Set-AdfsProperties -TlsClientPort 49443

Then restart the ADFS service on all nodes:

Restart-Service ADFSSRV

Now, is this a complete list of what can go wrong? Probably not, therefore be careful!

Have fun!

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Migration, Web Application Proxy | Leave a Comment »

(2019-03-05) Certificate Based Authentication In ADFS (Legacy And New) – The Complete Information To Get This Working

Posted by Jorge on 2019-03-05


ADFS supports many authentication methods for primary and secondary authentication, especially ADFS 2016 and its successor provide many authentication methods. “Certificate Based AuthN (CBA)” is one of those methods. It can be used for both INtranet and EXtranet scenarios in ADFS. How CBA is implemented depends on your ADFS version and the details of the SSL certificate.

When using ADFS 2012 R2 or earlier, or ADFS 2016 or later, without alternate hostname binding enabled, CBA will use the hostname “<Federation Service FQDN>” and port 49443. You must meet the following requirements:

  • ADFS and WAP Server Side
    • DNS Record
      • Internally: A record for <Federation Service FQDN> (e.g. FS.COMPANY.COM) pointing to either the ADFS servers (DNS load balancing) or a software/hardware load balancer for the ADFS Servers
      • Externally: A record for <Federation Service FQDN> (e.g. FS.COMPANY.COM) pointing to either the WAP servers (DNS load balancing) or a software/hardware load balancer for the WAP Servers
    • Service Principal Name
      • “HOST/<Federation Service FQDN>” (e.g. HOST/FS.COMPANY.COM) on the ADFS service account
    • Certificate Binding (ADFS/WAP Servers) (To view bindings: NETSH HTTP SHOW SSLCERT)
      • One for <Federation Service FQDN>:443 (e.g. FS.COMPANY.COM:443) bound to SSL certificate
      • One for <Federation Service FQDN>:49443 (e.g. FS.COMPANY.COM:49443) bound to SSL certificate
    • SSL Certificate (ADFS/WAP Servers):
      • Enhanced Key Usage
        • Server Authentication
      • Key Usage
        • Digital Signature
        • Key Encipherment
      • Subject:
        • <Federation Service FQDN> (e.g. FS.COMPANY.COM)
      • SAN:
        (REMARK: for other purposes you may need additional SANs!)
        • <Federation Service FQDN> (e.g. FS.COMPANY.COM)
  • User/Client Side
    • User Certificate (software based or smartcard):
      • Enhanced Key Usage
        • Client Authentication
        • Smart Card Logon (only needed when using a Smart Card!)
      • Key Usage
        • Digital Signature
      • Subject:
        • <Common Name> (e.g. CN=jorge) OR <Distinguished Name> (e.g. CN=jorge,CN=Users,DC=COMPANY,DC=COM)
      • SAN:
        (REMARK: for other purposes you may need additional SANs!)
        • <User Principal Name> (e.g. JORGE@COMPANY.COM)
    • Local Intranet Sites OR Trusted Sites (for both IE and Chrome!)
  • Load Balancer (only when using software/hardware based load balancer) (ADFS/WAP Servers):
    • Required configuration for the binding <Federation Service FQDN>:443 (e.g. FS.COMPANY.COM:443)
    • Required configuration for the binding <Federation Service FQDN>:49443 (e.g. FS.COMPANY.COM:49443)
  • Firewalls:
    • When the client is on the INternal network
      • Port 443 between client and the ADFS servers OR Load Balancer for the ADFS Servers
      • Port 49443 between client and thje ADFS servers OR Load Balancer for the ADFS Servers
    • When the client is on the EXternal network
      • Port 443 between client and the WAP servers OR the Load Balancer for the WAP Servers
      • Port 49443 between client and the WAP servers OR the Load Balancer for the WAP Servers
      • Port 443 between the WAP Servers and the ADFS Servers OR the Load Balancer for the ADFS Servers
      • Port 49443 between the WAP servers  and the ADFS Servers OR the Load Balancer for the ADFS Servers

When this “legacy” mode is enabled you will see the following when running:

Get-ADFSProperties   

image

Figure 1: Legacy Mode (TlsClientPort: 49443) Enabled For Certificate Based Authentication

image

Figure 2: Hostname Binding For The ADFS Service FQDN And Port 443 For Regular Federation Service Stuff

image

Figure 3: Hostname Binding For The ADFS Service FQDN And Port 49443 For Certificate Based Authentication

SNAGHTMLc02bbc6

Figure 4: Subject/SANs Of The ADFS SSL Certificate Supporting ONLY Legacy Certificated based Authentication

Now ADFS 2016 and higher supports a new mode for TLS Client Certificates over port 443, which is called “Alternate Host Name Binding”. This is useful when you have more stringent firewall restrictions. To enable this you need to run the following PowerShell command on just one ADFS server:

Set-ADFSAlternateTlsClientBinding –Thumbprint <ADFS SSL Certificate Thumbprint>

WARNING: This command configures a new binding on every ADFS server, reconfigures the TLS Client Port to 443 and will restart the ADFS service on every node!!!

 

image

Figure 5: Enabling “Alternate Host Name Binding”

With “Alternate Host Name Binding” in ADFS 2016 or later, CBA will use the hostname “CERTAUTH.<Federation Service FQDN>” and port 443. You must meet the following requirements (compared to the above changes in red):

  • ADFS and WAP Server Side
    • DNS Record
      (REMARK: You may already have an “A” record for your <Federation Service FQDN> (e.g. FS.COMPANY.COM). To create a new “A” record for CERTAUTH.<Federation Service FQDN> (e.g. CERTAUTH.FS.COMPANY.COM), that new record is a sub record of the <Federation Service FQDN>. In Windows DNS, when creating that record, it will convert the “A” record for the <Federation Service FQDN> to a folder that contains a record for “(same as parent folder)” and a record for CERTAUTH, both pointing to the ADFS Servers or WAP Servers)
      • Internally: A record for <Federation Service FQDN> (e.g. FS.COMPANY.COM) pointing to either the ADFS servers (DNS load balancing) or a software/hardware load balancer for the ADFS Servers
      • Externally: A record for <Federation Service FQDN> (e.g. FS.COMPANY.COM) pointing to either the WAP servers (DNS load balancing) or a software/hardware load balancer for the WAP Servers
      • Internally: A record for CERTAUTH.<Federation Service FQDN> (e.g. CERTAUTH.FS.COMPANY.COM) pointing to either the ADFS servers (DNS load balancing) or a software/hardware load balancer for the ADFS Servers
      • Externally: A record for CERTAUTH.<Federation Service FQDN> (e.g. CERTAUTH.FS.COMPANY.COM) pointing to either the WAP servers (DNS load balancing) or a software/hardware load balancer for the WAP Servers
    • Service Principal Name
      • “HOST/<Federation Service FQDN>” (e.g. HOST/FS.COMPANY.COM) on the ADFS service account
    • Certificate Binding (ADFS/WAP Servers) (To view bindings: NETSH HTTP SHOW SSLCERT)
      • One for <Federation Service FQDN>:443 (e.g. FS.COMPANY.COM:443) bound to SSL certificate
      • One for <Federation Service FQDN>:49443 (e.g. FS.COMPANY.COM:49443) bound to SSL certificate (although the binding is not needed, it will remain in place when migrating to Alternate Host Name Binding. No need to remove it. It also gives you the possibility to go back if needed for whatever reason!)
      • One for CERTAUTH.<Federation Service FQDN>:443 (e.g. CERTAUTH.FS.COMPANY.COM:443) bound to SSL certificate
    • SSL Certificate (ADFS/WAP Servers):
      • Enhanced Key Usage
        • Server Authentication
      • Key Usage
        • Digital Signature
        • Key Encipherment
      • Subject:
        • <Federation Service FQDN> (e.g. FS.COMPANY.COM)
      • SAN:
        (REMARK: for other purposes you may need additional SANs!)
        • <Federation Service FQDN> (e.g. FS.COMPANY.COM)
        • CERTAUTH.<Federation Service FQDN> (e.g. CERTAUTH.FS.COMPANY.COM)
          (REMARK: When a wildcard certificate is used it will present the error “There is a problem with this website’s security certificate.” or “This site is not secure (Error Code: DLG_FLAGS_SEC_CERT_CN_INVALID)” (IE) or “Your connection is not private (NET::ERR_CERT_COMMON_NAME_INVALID)” (Chrome))
  • User/Client Side
  • Load Balancer (only when using software/hardware based load balancer) (ADFS/WAP Servers):
    • Required configuration for the binding <Federation Service FQDN>:443 (e.g. FS.COMPANY.COM:443)
    • Required configuration for the binding <Federation Service FQDN>:49443 (e.g. FS.COMPANY.COM:49443)
    • Required configuration for the binding CERTAUTH.<Federation Service FQDN>:443 (e.g. CERTAUTH.FS.COMPANY.COM:443)
  • Firewalls:
    • When the client is on the INternal network
      • Port 443 between client and the ADFS servers OR Load Balancer for the ADFS Servers
      • Port 49443 between client and thje ADFS servers OR Load Balancer for the ADFS Servers
    • When the client is on the EXternal network
      • Port 443 between client and the WAP servers OR the Load Balancer for the WAP Servers
      • Port 49443 between client and the WAP servers OR the Load Balancer for the WAP Servers
      • Port 443 between the WAP Servers and the ADFS Servers OR the Load Balancer for the ADFS Servers
      • Port 49443 between the WAP servers  and the ADFS Servers OR the Load Balancer for the ADFS Servers

When this “legacy” mode is enabled you will see the following when running:

Get-ADFSProperties

SNAGHTMLc1dbd78

Figure 6: “Alternate Host Name Binding” Mode (TlsClientPort: 443) Enabled For Certificate Based Authentication

image

Figure 7: Subject/SANs Of The ADFS SSL Certificate Supporting Both Legacy Certificated based Authentication And “Alternate Host Name Binding”

image

Figure 8: Additional Hostname Binding For The ADFS Service FQDN And Port 443 For Certificate Based Authentication When Using “Alternate Host Name Binding”

Either modes support both primary and secondary authentication in ADFS! Works perfectly!

Now on the WAP servers, first implement the new certificate in the local certificate store, then run the following command to activate the new certificate and create the new certificate binding:

Set-WebApplicationProxySslCertificate -Thumbprint <WAP SSL Certificate Thumbprint>

Restart-Service ADFSSRV

Now imagine you have issues or for whatever reason you want to revert back to the legacy mode. Well that is an easy one. Just execute the following command on one ADFS server:

Set-AdfsProperties -TlsClientPort 49443

Then restart the ADFS service on all nodes:

Restart-Service ADFSSRV

Have fun!

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Certificate Based AuthN | 1 Comment »

(2019-02-22) Getting Rid Of Self-Signed Certs In Intermediate CA Store

Posted by Jorge on 2019-02-22


In the case of ADFS servers you may end up with self-signed certificates in the Intermediate CA store. Those self-signed certificates are most likely root CA certificates and those should be move to the root CA store.

After running the “Export-AdfsDiagnosticsFile” CMDlet on the (primary) ADFS server and uploading it to ADFS Help – Diagnostics Analyzer you might see something like shown below

image

Figure 1: Self-Signed Certificates Reported In The Intermediate CA Store By The ADFS Help Tool

With PowerShell you can find self-signed certificates by checking certificates and see if the subject is the same as the issuer

Get-ChildItem <Certificate Store> | ?{$_.Issuer -eq $_.Subject}

image

Figure 2: Self-Signed Certificates In The Intermediate CA Store

First you need to identity if any self-signed certificate is not a root CA certificate. In that case you can most likely remove that certificate from the intermediate CA store.

To remove a certificate from a certificate store you can use:

Get-ChildItem <Certificate Store>\<Certficate Thumbprint> | Remove-Item

Anything left can be moved from the intermediate CA store to the root CA store. To do that you can use the following:

$sourceCertStore = "Cert:\LocalMachine\CA"
$sourceCertStoreObject = Get-Item $sourceCertStore
$targetCertStore = "Cert:\LocalMachine\Root"
$targetCertStoreObject = Get-Item $targetCertStore
Get-ChildItem $sourceCertStore | ?{$_.Issuer -eq $_.Subject} | %{
    $thumbprint = $null
    $thumbprint = $_.Thumbprint
    $cert = $null
    $cert = Get-Item $sourceCertStore\$thumbprint
    If (!(Test-Path $targetCertStore\$thumbprint)) {
        Write-Host ""
        Write-Host "Adding Certificate With Thumbprint ‘$thumbprint’ To ‘$targetCertStore’" -ForegroundColor green
        $targetCertStoreObject.Open("ReadWrite")
        $targetCertStoreObject.Add($cert)
        $targetCertStoreObject.Close()
    } Else {
        Write-Host ""
        Write-Host "Certificate With Thumbprint ‘$thumbprint’ Already Exists In ‘$targetCertStore’" -ForegroundColor Red
    }
    If (Test-Path $targetCertStore\$thumbprint) {
        Write-Host "Removing Certificate With Thumbprint ‘$thumbprint’ From ‘$sourceCertStore’" -ForegroundColor green
        $sourceCertStoreObject.Open("ReadWrite")
        $sourceCertStoreObject.Remove($cert)
        $sourceCertStoreObject.Close()
    }
}

image

Figure 3: Moving Certificates From The Intermediate CA Store To The Root CA Store

Have fun!

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Certificates, PowerShell | Leave a Comment »

(2019-02-14) Enabling Device Registration/Authentication In ADFSv4 Fails

Posted by Jorge on 2019-02-14


As mentioned in Configure Device Registration for Hybrid Windows Hello for Business device registration and authentication must be enabled in ADFS to support Azure AD Device Authentication on-premises against ADFS. It describes the steps on how to achieve this.

You start with:

Initialize-ADDeviceRegistration -ServiceAccountName <Service Account In ADFS> -DeviceLocation <FQDN AD Domain Storing Device Objects From AAD>

image

Figure 1: Initializing Device Registration In AD

This creates the required DRS objects in the configuration NC and in the domain NC specified to host the AAD devices written back to AD.

Looking in ADFS in the “Device Registration” node you will see the following, which is weird.

image

Figure 2: Device registration Overview Mentioning It Still Needs To Be Configured

Clicking on “Configure Device Registration” results in the following message. Just click “OK” to continue

image

Figure 3: Message After Clicking “Configure Device Registration”

Waiting until it finishes results in the exact same state as displayed in figure 2. Huh?

In PowerShell executing the following command:

Get-AdfsDeviceRegistration

…does not display the DN of the DRS objects that are in AD. It should specify a value for DrsObjectDN and DeviceObjectLocation, but it does not as you can see or even experience yourself. The event logs do not give you information of why not.

image

Figure 4: Empty Values For DrsObjectDN And DeviceObjectLocation

After some digging around, I found that in my ADFSv4 the EnrollmentServer endpoint was disabled and because of that it caused the device registration configuration to not succeed.

image

Figure 5: EnrollmentServer Endpoint Being Disabled

After enabling the EnrollmentServer endpoint through the GUI and restarting the ADFS service on every ADFS server in the ADFS farm (or using the PowerShell commands below)

Get-AdfsEndpoint /EnrollmentServer/

Enable-AdfsEndpoint /EnrollmentServer/

Set-AdfsEndpoint /EnrollmentServer/ -Proxy $True

Get-AdfsEndpoint /EnrollmentServer/

Restart-Service ADFSSRV # Execute On EVERY ADFS Server!

image

Figure 6: Enabling The EnrollmentServer Endpoint

Now you can see that there are values for DrsObjectDN and DeviceObjectLocation

Get-AdfsDeviceRegistration

image

Figure 7: Values For DrsObjectDN And DeviceObjectLocation

image

Figure 8: Device Registration And Device Authentication Now Being Enabled In ADFS

Have fun!

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Device Registration | Leave a Comment »

(2019-02-08) Troubleshooting HTTPS/LDAPS

Posted by Jorge on 2019-02-08


My ADFS environment has an attribute store configured to an ADLDS and for that I used the “ldapattributestore” that still is available in the codeplex archives (https://archive.codeplex.com/?p=ldapattributestore). Because that ADLDS instance was running on a DC with ADDS, I configured the ADLDS instance to use port 5389 for LDAP and port 5636 for LDAPS. The “connection" string” for that LDAP Attribute Store was configured to use a secure connection (i.e. LDAPS) over port 5636. As I was checking functionality of my test environment I also tested this part by targeting the “Show My Claims” app (https://jorgequestforknowledge.wordpress.com/2015/07/04/displaying-the-issued-claims-in-a-security-token-on-screen/) that dives into that LDAP Attribute Store and displays specific claims on screen.

As I did not use my test environment for some time, several certs were expired and needed replacement. I opened the Local Machine certificate store and replaced every certificate that was expired or was going to expire soon with a new certificate using the exact same subject and SANs. After updating all certificates I started configuring and testing every single application using a certificate. So as you can imagine at some point in time I ended up with ADFS, the Show My Claims web site and with that the LDAPS attribute.

As an initial test I accessed the Show My Claims web site and due to the Issuance Transform Rules ADFS needed to dive into the ADLDS attribute store to source claims being displayed on screen. Unfortunately that failed. Looking at the ADFS Admin Event Log, ADFS was having issues accessing the Attribute Store. Those issues were related to the usage of LDAPS.

In that case I needed to start the basic testing of LDAPS through the good old LDP and see what was going on.

So after starting LDP and entered the FQDN of the ADLDS instance and its configured LDAPS port   

image

Figure 1: Starting LDP And Connecting To The ADLDS Instance Using The FQDN, The LDAPS Port

After clicking OK I was not surprised about the error “cannot open connection”. The more interesting question was “WHY?”

image

Figure 2: Error When Connecting To The ADLDS Instance

For this ADLDS instance I had a certificate with a subject and SAN that contained “IDSTORE.IAMTEC.NL”. I also permissioned the corresponding private key with the service account being used by the ADLDS instance. So far so good, but even with that it did not work. That’s when I decided to check all the requirements of a certificate to be used for LDAPS and used the following Microsoft article:

The certificate that I was using fulfilled all requirements and with that in mind it was time to enable debug logging for SCHANNEL when using HTTPS or LDAPS:

To make sure I was not missing any information, I configured the following for debug logging of SCHANNEL:

  • 0x0001 Log error messages
  • 0x0002 Log warnings
  • 0x0004 Log informational and success events

After enabling debug logging for SCHANNEL I tried it again with LDP and in the SYSTEM Event Log I saw the following error.   

image

Figure 3: Error When Accessing The Private Key

A fatal error occurred when attempting to access the TLS server credential private key. The error code returned from the cryptographic module is 0x8009030D. The internal error state is 10001.

I reconfirmed the certificate for IDSTORE.IAMTEC.NL had its private key configured for the service account in use by the ADLDS instance. It still did nit work

I also saw the following event in the SYSTEM Event Log

image

Figure 4: The Private Key Being Used By The ADLDS Instance

The TLS server credential’s private key has the following properties:

   CSP name: Microsoft RSA SChannel Cryptographic Provider
   CSP type: 12
   Key name: d40c17eadd0fb4c1e33541e54ebf55b1_c9c5687f-fc0b-4765-bc6d-2435ba59e1b2
   Key Type: key exchange
    Key Flags: 0x20

The attached data contains the certificate.

The event shown above mentioned the private key being used by the the ADLDS instance, but it still did not mention which certificate was being used. Switching to the details TAB, it told me more about the corresponding certificate that was being used. Going through the data I noticed it contained the SANs “*.IAMTEC.NET” and “*.IAMTEC.NL”. That was surprising to me as the certificate that envisioned for the ADLDS only contained “IDSTORE.IAMTEC.NL” as subject and as SAN.

image

Figure 5: The Certificate Data That Belong To The Private Key

After seeing this I remembered the following listed in the first MSFT article:

Multiple SSL certificates

Schannel, the Microsoft SSL provider, selects the first valid certificate that it finds in the local computer store. If there are multiple valid certificates available in the local computer store, Schannel may not select the correct certificate

What I never realized was that my wildcard certificate was going to be used first before even considering the usage of the certificate that contained the more specific subject and SAN.

As displayed below I permissioned the private key that belonged to the wildcard certificate ….

image

Figure 6: Permissioning The Private Key Of The Wildcard Certificate

Retried my test with LDP as shown below….

image

Figure 7: Retrying The LDAPS Test With DP

….and now it worked. You can see at the top it is connecting securely through LDAPS and that it is using a cipher strength of 256 bits

After this I check the LDAP Attribute Store configuration to make sure everything was configured correctly. And it was. Retrying accessing the Show My Claims site I was able to the claims that were sourced from the ADLDS instance

Check!

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Domain Services (ADDS), Active Directory Federation Services (ADFS), Active Directory Lightweight Directory Services (ADLDS), Attribute Store, Certificates, Claim Types, LDAPS, LDAPS, LDP | Leave a Comment »

(2018-11-01) Transform Rules In ADFS – Send E-Mail Address Value For E-mail, Otherwise Send UPN Value For E-Mail

Posted by Jorge on 2018-11-01


A few days ago I got the following question:

  • Some accounts have a mailbox, some do not;
  • For accounts that do have a mailbox I need to send the e-mail address value as the claim value in the e-mail address claim type;
  • For accounts that do not have a mailbox I need to send the upn value as the claim value in the e-mail address claim type;

How can I achieve that through the claims rule language in ADFS?

It is not that difficult. See below for an example as the answer to the question above:

RULENAME1: User Identity Claims – Windows Account Name
COMMENT1: if the windows account name claim exists and has a value send it through

c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
=> issue(claim = c);

RULENAME2: User Identity Claims – upn
COMMENT2: if the UPN claim exists and has a value send it through

c:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> issue(claim = c);

RULENAME3: User Identity Claims – E-Mail Address
COMMENT3: get mail from AD and put it in claim

c:[Type == "
http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"), query = ";mail;{0}", param = c.Value);

RULENAME4: System Claims – Check E-Mail Address Existence
COMMENT4: check if the mail address claim exist or not

NOT EXISTS([Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"])
=> add(Type = "http://temp.org/system/claims/eMailAddressExistance", Value = "False");

RULENAME5: User Identity Claims – upn To E-Mail Address (When E-Mail Address DOES NOT Exist)
COMMENT5: send the UPN value into mail address claim if no mail claim address exists

c1:[Type == "
http://temp.org/system/claims/eMailAddressExistance", Value == "False"] &&
c2:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", Value = c2.Value);

Make sure to test this first in a TEST environment!

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Claims, Claims Rule Language | Leave a Comment »

(2018-10-24) Setting/Fixing The Correct Permissions On Your ADFS Certificates And/Or On The Certificate Sharing Container

Posted by Jorge on 2018-10-24


Are the permissions on any of the private keys of your certificates in use by ADFS and/or the certificate sharing container screwed up? If YES, then you can use the PowerShell code below to fix those permissions for the account the ADFS Service is running under. Make sure to test this is a test environment first!

### Function To Permission Private Key Of Custom/Non-ADFS Managed Certificates
Function permissionPrivateKey($certificate,$certType,$svcAccount) {
    $ace = $svcAccount,"Read,Synchronize","Allow"
    $machineKeysLocation = $ENV:ALLUSERSPROFILE + "\Microsoft\Crypto\RSA\MachineKeys\"
    $CertKeyFile = $certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
    $CertKeyFileFullPath = $MachineKeysLocation + $CertKeyFile
    $CertKeyFileACL = Get-Acl $CertKeyFileFullPath
    Write-Host "+++ RESULT +++" -ForeGroundColor Magenta
    $certSubject = $null
    $certSubject = $certificate.Subject
    Write-Host "Certificate Type……..: $certType" -ForegroundColor Yellow
    Write-Host "Certificate Subject…..: $certSubject" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Private Key Permissions (BEFORE)" -ForegroundColor Yellow
    $CertKeyFileACL.Access | FT @{n='[Account]’;e={$_.IdentityReference}},@{n='[Control]’;e={$_.AccessControlType}},@{n='[Permissions]’;e={$_.FileSystemRights}}
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $ace
    $CertKeyFileACL.SetAccessRule($accessRule)
    $CertKeyFileACL | Set-Acl $CertKeyFileFullPath
    $CertKeyFileACL = $null
    $CertKeyFileACL = Get-Acl $CertKeyFileFullPath
     Write-Host ""
    Write-Host "Private Key Permissions (AFTER)" -ForegroundColor Yellow
    $CertKeyFileACL.Access | FT @{n='[Account]’;e={$_.IdentityReference}},@{n='[Control]’;e={$_.AccessControlType}},@{n='[Permissions]’;e={$_.FileSystemRights}}
}
   
### Determining Current ADFS Service Account
$adfsService = Get-WmiObject win32_service -filter "name=’ADFSSRV’"
$currentADFSServiceAccount = $adfsService.StartName

### Determining Database Type Being Used
$adfsSTS = Get-WmiObject -namespace root/ADFS -class SecurityTokenService
$configDBConnectionString = $adfsSTS.ConfigurationDatabaseConnectionString
If ($configDBConnectionString.contains("\\.\pipe\")) {
    Write-Host ""
    Write-Host "Windows Internal Database Is Being Used" -ForegroundColor Yellow
     $dbType = "WID"
    $roleADFSServer = (Get-AdfsSyncProperties).Role
    If ($roleADFSServer -eq "SecondaryComputer") {
         Write-Host ""
        Write-Host "Running On Secondary ADFS Server" -ForegroundColor Yellow
        Function portConnectionCheck($fqdnServer,$port,$timeOut) {
            $tcpPortSocket = $null
            $portConnect = $null
            $tcpPortWait = $null
            $tcpPortSocket = New-Object System.Net.Sockets.TcpClient
            $portConnect = $tcpPortSocket.BeginConnect($fqdnServer,$port,$null,$null)
            $tcpPortWait = $portConnect.AsyncWaitHandle.WaitOne($timeOut,$false)
            If(!$tcpPortWait) {
                $tcpPortSocket.Close()
                 Return "ERROR"
            } Else {
                $ErrorActionPreference = "SilentlyContinue"
                $tcpPortSocket.EndConnect($portConnect) | Out-Null
                If (!$?) {
                    Return "ERROR"
                } Else {
                    Return "SUCCESS"
                }
                 $tcpPortSocket.Close()
                $ErrorActionPreference = "Continue"
            }
        }
        $primaryADFSServer = (Get-AdfsSyncProperties).PrimaryComputerName
        $adfsWIDIsSecondary = $true
    } Else {
        Write-Host "Running On Primary ADFS Server" -ForegroundColor Yellow
        $adfsWIDIsSecondary = $false
    }
} Else {
    Write-Host "SQL Server Is Being Used" -ForegroundColor Yellow
    $dbType = "SQL"
}

### Getting ADFS Properties And Certificates
If ($dbType -eq "WID") {
    If ($adfsWIDIsSecondary) {
        $ports = 5985,443,80 # WinRM For Remote PowerShell, ADFS HTTPS, ADFS HTTP
        $connectionCheckOK = $true
        $ports | %{
            $port = $null
            $port = $_
            $connectionResult = $null
            $connectionResult = portConnectionCheck $primaryADFSServer $port 500
            If ($connectionResult -eq "ERROR") {
                $connectionCheckOK = $false
            }
        }
        If ($connectionCheckOK) {
            $primaryADFSServerSession = New-PSSession -ComputerName $primaryADFSServer
            $fedSvcConfig = Invoke-Command -Session $primaryADFSServerSession -ScriptBlock {
                $fedSvcProperties = Get-AdfsProperties
                $fedSvcCertificates = Get-AdfsCertificate
                Return $fedSvcProperties,$fedSvcCertificates
            }
            Remove-PSSession $primaryADFSServerSession
            $fedSvcProps = $fedSvcConfig[0]
            $fedSvcCerts = $fedSvcConfig[1]
        } Else {
             Write-Host ""
            Write-Host "The Primary ADFS Server IS NOT Reachable" -ForegroundColor Red
            Write-Host "Aborting…" -ForegroundColor Red
            Write-Host ""
            EXIT
        }
    } Else {
        $fedSvcProps = Get-AdfsProperties
        $fedSvcCerts = Get-AdfsCertificate
     }
}
If ($dbType -eq "SQL") {
    $fedSvcProps = Get-AdfsProperties
    $fedSvcCerts = Get-AdfsCertificate
}

### Checking If Certificate Sharing Container Has Been Configured
If ($fedSvcProps.CertificateSharingContainer) {
    Write-Host ""
    Write-Host "Certificate Sharing Container IS Configured" -ForegroundColor Yellow
    $certSharingContainerConfigured = $true
    $certSharingContainerState = "Configured"
    $certSharingContainerDN = ($fedSvcProps.CertificateSharingContainer).ToString()
} Else {
     Write-Host ""
    Write-Host "Certificate Sharing Container IS NOT Configured" -ForegroundColor Yellow
    $certSharingContainerConfigured = $false
    $certSharingContainerState = "NOT Configured"
    $certSharingContainerDN = "N.A."
}

### Checking If Custom Certificates Are Being Used Or ADFS Managed Self-Signed Certificates For Token Signing/Encryption
If ($fedSvcProps.AutoCertificateRollover -eq $false) {
    Write-Host ""
    Write-Host "ADFS Managed Self-Signed Certs ARE NOT Being Used" -ForegroundColor Yellow
    $adfsManagedCerts = $false
    $certManagement = "NON-ADFS Managed"
} ElseIf ($fedSvcProps.AutoCertificateRollover -eq $true) {
    Write-Host ""
    Write-Host "ADFS Managed Self-Signed Certs ARE Being Used" -ForegroundColor Yellow
    $adfsManagedCerts = $true
    $certManagement = "ADFS Managed"
}

### Displaying All The Info Gathered
Invoke-Command -ScriptBlock {
    Write-Host ""
    Write-Host "Database Type………………………: $dbType" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Certificate Sharing Container State…..: $certSharingContainerState" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Certificate Sharing Container DN……..: $certSharingContainerDN" -ForegroundColor Yellow
    Write-Host ""
     Write-Host "Certificate Management………………: $certManagement" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Current Service Account……………..: $currentADFSServiceAccount" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Token-Signing Certificate(s)…" -ForegroundColor Yellow
    $fedSvcTokenSigningCert = $fedSvcCerts | ?{$_.CertificateType -eq "Token-Signing"}
    $fedSvcTokenSigningCert | FT Thumbprint,@{n=’Subject’;e={$_.Certificate.Subject}},@{n=’Not Before’;e={$_.Certificate.NotBefore}},@{n=’Not After’;e={$_.Certificate.NotAfter}}
    Write-Host "Token-Encryption Certificate(s)…" -ForegroundColor Yellow
    $fedSvcTokenEncryptCert = $fedSvcCerts | ?{$_.CertificateType -eq "Token-Decrypting"}
    $fedSvcTokenEncryptCert | FT Thumbprint,@{n=’Subject’;e={$_.Certificate.Subject}},@{n=’Not Before’;e={$_.Certificate.NotBefore}},@{n=’Not After’;e={$_.Certificate.NotAfter}}
    Write-Host "Service Communications / SSL Certificate…" -ForegroundColor Yellow
    $fedSvcSvcCommCert = $fedSvcCerts | ?{$_.CertificateType -eq "Service-Communications"}
    $fedSvcSvcCommCert | FT Thumbprint,@{n=’Subject’;e={$_.Certificate.Subject}},@{n=’Not Before’;e={$_.Certificate.NotBefore}},@{n=’Not After’;e={$_.Certificate.NotAfter}}
}

### Setting Permissions On Private Key Of Custom Token Certificates
If (!$adfsManagedCerts) {
    Write-Host ""
    Write-Host "Permissioning Custom Token Certificates" -ForegroundColor Yellow
    $certStoreLocation = "Cert:\LocalMachine\My"
    $fedSvcCerts | ?{$_.CertificateType -ne "Service-Communications"} | %{
        $certificateType = $null
        $certificateType = $_.CertificateType
        $certificateThumbprint = $null
        $certificateThumbprint = $_.Thumbprint
        $certificateInStore = $null
        $certificateInStore = Get-ChildItem $($certStoreLocation + "\" + $certificateThumbprint) -ErrorAction SilentlyContinue
        If ($certificateInStore -And $certificateInStore.HasPrivateKey) {
            permissionPrivateKey $certificateInStore $certificateType $currentADFSServiceAccount
        } Else {
             Write-Host ""
            Write-Host "The Certificate With Thumbprint ‘$certificateThumbprint’ ($certificateType) Does Not Exist" -ForegroundColor Red
            Write-Host "Or" -ForegroundColor Red
            Write-Host "The Certificate With Thumbprint ‘$certificateThumbprint’ ($certificateType) Does Not Have A Private Key" -ForegroundColor Red
            Write-Host ""
        }
    }
}

### Setting Permissions On Private Key Of SSL/Service-Communication Certificate
$fedSvcCerts | ?{$_.CertificateType -eq "Service-Communications"} | %{
    $certificateType = $null
    $certificateType = $_.CertificateType
    $certificateThumbprint = $null
    $certificateThumbprint = $_.Thumbprint
     $certificateInStore = $null
    $certificateInStore = Get-ChildItem $($certStoreLocation + "\" + $certificateThumbprint) -ErrorAction SilentlyContinue
    If ($certificateInStore -And $certificateInStore.HasPrivateKey) {
        permissionPrivateKey $certificateInStore $certificateType $currentADFSServiceAccount
    } Else {
        Write-Host ""
        Write-Host "The Certificate With Thumbprint ‘$certificateThumbprint’ ($certificateType) Does Not Exist" -ForegroundColor Red
        Write-Host "Or" -ForegroundColor Red
        Write-Host "The Certificate With Thumbprint ‘$certificateThumbprint’ ($certificateType) Does Not Have A Private Key" -ForegroundColor Red
        Write-Host ""
    }
}

### If Configured Setting Permissions On Certificate Sharing Container
### WARNING: ADDS PowerShell Module Required!!! – Will Be Installed!
If ($certSharingContainerConfigured) {
    Write-Host ""
    Write-Host "Certificate Sharing Container Is Configured Used" -ForegroundColor Yellow

    # Install RSAT PowerShell Tools And Load Module
    Install-WindowsFeature RSAT-AD-Tools -IncludeAllSubFeature
     Import-Module ActiveDirectory

    # Get The Certificate Sharing Container DN, Its ACL And Present The Results Of That
    $dnPathCertSharingContainer = ($fedSvcProps.CertificateSharingContainer).ToString()
    $dnPathCertSharingContainerPath = $(Join-Path "AD:\" $dnPathCertSharingContainer)
    Write-Host ""
    Write-Host "Certificate Sharing Container Permissions (BEFORE)" -ForegroundColor Yellow
    $aclCertSharingContainer = Get-Acl $dnPathCertSharingContainerPath
    $aclCertSharingContainer.Access | FT @{n='[Account]’;e={$_.IdentityReference}},@{n='[Control]’;e={$_.AccessControlType}},@{n='[Permissions]’;e={$_.ActiveDirectoryRights}}
   
    # Object Class And Inheritance Scope
    $schemaIDGUIDScopedObject = [guid]"00000000-0000-0000-0000-000000000000"
    $inheritanceScope = "All"

    # Security Principal To Assign Permissions To
    $securityPrincipalAccount = $currentADFSServiceAccount
    $securityPrincipalObject = New-Object System.Security.Principal.NTAccount($securityPrincipalAccount)

    # Define ACE
    $rightsCollection = [System.DirectoryServices.ActiveDirectoryRights]::"CreateChild","Self","WriteProperty","DeleteTree","GenericRead","WriteOwner"
    $aclType = [System.Security.AccessControl.AccessControlType]::"Allow"
    $aceDefinition = $securityPrincipalObject,$rightsCollection,$aclType,$schemaIDGUIDScopedObject,$inheritanceScope
    $accessRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($aceDefinition)   

    # Set The New Access Rule
    $aclCertSharingContainer.AddAccessRule($accessRule)
    $aclCertSharingContainer | Set-Acl $dnPathCertSharingContainerPath

    # Get The Certificate Sharing Container ACL And Present The Results Of That
    Write-Host ""
    Write-Host "Certificate Sharing Container Permissions (AFTER)" -ForegroundColor Yellow
    $aclCertSharingContainer = Get-Acl $dnPathCertSharingContainerPath
    $aclCertSharingContainer.Access | FT @{n='[Account]’;e={$_.IdentityReference}},@{n='[Control]’;e={$_.AccessControlType}},@{n='[Permissions]’;e={$_.ActiveDirectoryRights}}
    $aclCertSharingContainer.Access | ?{$_.IdentityReference -eq $securityPrincipalAccount} | FT @{n='[Account]’;e={$_.IdentityReference}},@{n='[Control]’;e={$_.AccessControlType}},@{n='[Permissions]’;e={$_.ActiveDirectoryRights}}
    $aclCertSharingContainer.Access | ?{$_.IdentityReference -eq $securityPrincipalAccount}
}

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Certificates, PowerShell | Leave a Comment »

(2018-10-23) How Do You Know Your ADFS Server Is Lacking Permissions On Its Certificates?

Posted by Jorge on 2018-10-23


Even through the ADFS Service starts and everything “appears” to be right, NOTHING works! In the ADFS Admin Event Log you may see the following event

image

Figure 1: An Error In The ADFS Admin Event Log Referencing The Lack Of Permissions On The Private Key

There was an error in enabling endpoints of Federation Service. Fix configuration errors using PowerShell cmdlets and restart the Federation Service.

Additional Data
Exception details:
System.ArgumentNullException: Value cannot be null.
Parameter name: certificate
    at System.IdentityModel.Tokens.X509SecurityToken..ctor(X509Certificate2 certificate, String id, Boolean clone, Boolean disposable)
    at Microsoft.IdentityServer.Service.Configuration.MSISSecurityTokenServiceConfiguration.Create(Boolean forSaml, Boolean forPassive)
    at Microsoft.IdentityServer.Service.Policy.PolicyServer.Service.ProxyPolicyServiceHost.ConfigureWIF()
    at Microsoft.IdentityServer.Service.SecurityTokenService.MSISConfigurableServiceHost.Configure()
    at Microsoft.IdentityServer.Service.Policy.PolicyServer.Service.ProxyPolicyServiceHost.Create()
    at Microsoft.IdentityServer.ServiceHost.STSService.StartProxyPolicyStoreService(ServiceHostManager serviceHostManager)
    at Microsoft.IdentityServer.ServiceHost.STSService.OnStartInternal(Boolean requestAdditionalTime)

The solution? Fix the permissions on the private keys and restart the ADFS Service on every ADFS server where the permissions were fixed

When the ADFS Service is finished starting your should ALWAYS see the following informational events (may be slightly different depending on the version of Windows):

  • Event ID 397 (WinHTTP Settings)
  • Event ID 349 (Administration Service)
  • Event ID 251 (For Every Attribute Store)
  • Event ID 278 (SAML Artifact)
  • Event ID 106 (For Every Authentication Provider (Multiple Times))
  • Event ID 100 (Federation Service Started Successfully)
  • Event ID 298 (Windows Hello For Business)
  • Event ID 399 (Certificate Archiving)
  • Event ID 386 (Certificate Expiration)
  • ….And Last But Not Least

image

Figure 2: ADFS Mentioning Everything Is Correct Regarding The ADFS Certificates

AD FS detected that all the service certificates have appropriate access given to the AD FS service account.

Cheers,
Jorge

————————————————————————————————————————————————————-
This posting is provided "AS IS" with no warranties and confers no rights!
Always evaluate/test everything yourself first before using/implementing this in production!
This is today’s opinion/technology, it might be different tomorrow and will definitely be different in 10 years!
DISCLAIMER:
https://jorgequestforknowledge.wordpress.com/disclaimer/
————————————————————————————————————————————————————-
########################### Jorge’s Quest For Knowledge ##########################
####################
http://JorgeQuestForKnowledge.wordpress.com/ ###################
————————————————————————————————————————————————————-

Posted in Active Directory Federation Services (ADFS), Certificates | Leave a Comment »

 
%d bloggers like this: