Problem
You’ve completed deploying the configuration required that allow clients to use AD FS (on Windows Server 2019) claims-based authentication to connect to Exchange Server 2019 Outlook on the web (formerly known as Outlook Web App) and the Exchange admin center (EAC) as outlined in the following documentation:
Use AD FS claims-based authentication with Outlook on the web
https://docs.microsoft.com/en-us/exchange/clients/outlook-on-the-web/ad-fs-claims-based-auth?view=exchserver-2019
… but notice that attempting to navigate to /owa throws two different errors depending on the browser you use:
Google Chrome:
The page isn’t working
mail.contoso.com redirected you too many times.
ERR_TOO_MANY_REDIRECTS
Internet Explorer:
Server Error in '/owa' Application.
Encryption certificate is absent
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Microsoft.Exchange.Security.Authentication.AdfsConfigurationException: Encryption certificate is absent
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[AdfsConfigurationException: Encryption certificate is absent]
Microsoft.Exchange.Security.Authentication.Utility.GetCertificates() +130
Microsoft.Exchange.Security.Authentication.AdfsSessionSecurityTokenHandler.CreateTransforms() +12
Microsoft.Exchange.Security.Authentication.AdfsFederationAuthModule.FederatedAuthentication_ServiceConfigurationCreated(Object sender, ServiceConfigurationCreatedEventArgs e) +143
Microsoft.IdentityModel.Web.FederatedAuthentication.get_ServiceConfiguration() +177
Microsoft.IdentityModel.Web.HttpModuleBase.Init(HttpApplication context) +17
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +580
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +165
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +267
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +341
[HttpException (0x80004005): Encryption certificate is absent]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +523
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +107
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +688
Attempting to navigate to /ecp throws the following error:
Server Error in '/ecp' Application.
Runtime Error
Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
Details: To enable the details of this specific error message to be viewable on remote machines, please create a <customErrors> tag within a "web.config" configuration file located in the root directory of the current web application. This <customErrors> tag should then have its "mode" attribute set to "Off".
<!-- Web.Config Configuration File --> <configuration> <system.web> <customErrors mode="Off"/> </system.web> </configuration> |
Notes: The current error page you are seeing can be replaced by a custom error page by modifying the "defaultRedirect" attribute of the application's <customErrors> configuration tag to point to a custom error page URL.
<!-- Web.Config Configuration File --> <configuration> <system.web> <customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/> </system.web> </configuration> |
Reviewing the event logs shows the following error consistently logged on the Exchange server:
Log Name: Application
Source: ASP.NET 4.0.30319.0
Event ID: 1309
Level: Warning
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 4/23/2020 2:41:17 PM
Event time (UTC): 4/23/2020 5:41:17 PM
Event ID: 034a726997a145338d6d7f878e25b637
Event sequence: 2
Event occurrence: 1
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/1/ROOT/owa-20-132321372689777583
Trust level: Full
Application Virtual Path: /owa
Application Path: E:\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\
Machine name: OSMIUM
Process information:
Process ID: 14576
Process name: w3wp.exe
Account name: NT AUTHORITY\SYSTEM
Exception information:
Exception type: AdfsConfigurationException
Exception message: Encryption certificate is absent
at Microsoft.Exchange.Security.Authentication.Utility.GetCertificates()
at Microsoft.Exchange.Security.Authentication.AdfsSessionSecurityTokenHandler.CreateTransforms()
at Microsoft.Exchange.Security.Authentication.AdfsFederationAuthModule.FederatedAuthentication_ServiceConfigurationCreated(Object sender, ServiceConfigurationCreatedEventArgs e)
at Microsoft.IdentityModel.Web.FederatedAuthentication.get_ServiceConfiguration()
at Microsoft.IdentityModel.Web.HttpModuleBase.Init(HttpApplication context)
at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)
at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context)
at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)
Request information:
Request URL: https://mail.contoso.bm:443/owa/
Request path: /owa/
User host address: 172.16.10.105
User:
Is authenticated: False
Authentication Type:
Thread account name: NT AUTHORITY\SYSTEM
Thread information:
Thread ID: 18
Thread account name: NT AUTHORITY\SYSTEM
Is impersonating: False
Stack trace: at Microsoft.Exchange.Security.Authentication.Utility.GetCertificates()
at Microsoft.Exchange.Security.Authentication.AdfsSessionSecurityTokenHandler.CreateTransforms()
at Microsoft.Exchange.Security.Authentication.AdfsFederationAuthModule.FederatedAuthentication_ServiceConfigurationCreated(Object sender, ServiceConfigurationCreatedEventArgs e)
at Microsoft.IdentityModel.Web.FederatedAuthentication.get_ServiceConfiguration()
at Microsoft.IdentityModel.Web.HttpModuleBase.Init(HttpApplication context)
at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)
at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(sIntPtr appContext, HttpContext context)
at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)
Custom event details:
Solution
This issue took quite a bit of my time to troubleshoot as I thought I had made a mistake for the configuration outlined in the document. What I later determined from the event constantly logged shown above was that the self-signed Microsoft Exchange Server Auth Certificate on the Exchange 2019 servers have expired and it was causing the authentication redirect to the AD FS server to fail. To quickly determine whether this is the case for an environment, simply launch the event viewer on one of the Exchange servers, navigate to the Application logs and filter based on Event ID 24:
You should see an event similar to the following:
Log Name: Application
Source: MSExchange Web Services
Event ID: 24
Level: Error
The Exchange certificate [Subject]
CN=Microsoft Exchange Server Auth Certificate
[Issuer]
CN=Microsoft Exchange Server Auth Certificate
[Serial Number]
2BF79A269A16ACB047DE62C555EAF2B7
[Not Before]
3/18/2015 2:36:19 PM
[Not After]
2/20/2020 1:36:19 PM
[Thumbprint]
E60327C0FFB444247A6CD5E2BAD6AD58083BD6F1
expired on 2/20/2020 1:36:19 PM.
The certificate in this environment expired on February 20, 2020 and while this Exchange Server 2019 wasn’t installed 5 years ago (this is the default lifetime of the self-signed certificate), the first Exchange Server 2013 or 2016 was probably installed sometime in 2015. This certificate is installed on every Exchange server in the organization and shared as it is not unique to the identity of any of the servers.
To renew this certificate, begin by executing the following cmdlet to display the certificates on the Exchange server and confirm that the Microsoft Exchange Server Auth Certificate listed has indeed expired:
Get-ChildItem cert:\localmachine\my | ft Thumbprint,Notafter,Subject
Use the Get-AuthConfig cmdlet to confirm that the expired certificate is being used:
Note the matching thumbprint.
Use the following cmdlet to retrieve the thumbprint of the expired certificate:
Get-AuthConfig | fl Currentcer*
Copy the Thumbprint down as you will need this later.
Note that if the certificate has expired then you can simply renew it directly from the EAC console but I had issues accessing the EAC so I decided to use PowerShell to perform the renewal as outlined in the documentation here:
Renew an Exchange Server certificate
https://docs.microsoft.com/en-us/exchange/architecture/client-access/renew-certificates?view=exchserver-2019
Execute the following cmdlet to list all of the certificates the Exchange server is using and confirm that the previously copied thumbprint matches the one listed as Subject: CN=Microsoft Exchange Server Auth Certificate :
Get-ExchangeCertificate | where {$_.IsSelfSigned -eq $true} | Format-List FriendlyName,Subject,CertificateDomains,Thumbprint,NotBefore,NotAfter
Execute the following cmdlet to retrieve the expired certificate as an object then renew it with the New-ExchangeCertificate cmdlet:
Get-ExchangeCertificate -Thumbprint <paste the thumbprint previous copied> | New-ExchangeCertificate -Force -PrivateKeyExportable $true
Here is an example of the cmdlet ran with the thumbprint copied previously:
Get-ExchangeCertificate -Thumbprint E60327C0FFB444247A6CD5E2BAD6AD58083BD6F1 | New-ExchangeCertificate -Force -PrivateKeyExportable $true
Copy the thumbprint to notepad and clearly label this is the renewed certificate.
Executing the previous cmdlet:
Get-ExchangeCertificate | where {$_.IsSelfSigned -eq $true} | Format-List FriendlyName,Subject,CertificateDomains,Thumbprint,NotBefore,NotAfter
… will now show the expired and renewed certificate:
If you’re like me where you’re unable to access EAC, you can view the new certificate in the IIS console as well:
Execute the Get-AuthConfig cmdlet and make a note of the that the CurrentCertificateThumbprint is populated while the PreviousCertificateThumbprint and NextCertificateThumbprint are empty:
Proceed to replace the expired certificate by executing the following cmdlets:
$thumb = "< The New Certificate Thumbprint>"
$date = get-date
Set-AuthConfig -NewCertificateThumbprint $thumb -NewCertificateEffectiveDate $date
Here is an example of the cmdlet to execute with the information above:
$thumb = “BDE4266ED877E95F38D303878A048C0EA0183C7B”
$date = get-date
Set-AuthConfig -NewCertificateThumbprint $thumb -NewCertificateEffectiveDate $date
Execute the Get-AuthConfig cmdlet and notice how that the CurrentCertificateThumbprint hasn’t changed but the NextCertificateThumbprint field is now populated with the new certificate’s thumbprint:
Proceed to publish the new certificate and clearing the old expired certificate from the configuration by executing the following cmdlets:
Set-AuthConfig -PublishCertificate
Set-AuthConfig -ClearPreviousCertificate
Execute the Get-AuthConfig cmdlet and notice how that the CurrentCertificateThumbprint has been updated with the new certificate’s thumbprint and the NextCertificateThumbprint field is cleared:
Proceed and confirm that these events are no longer logged:
… then test to confirm that the /owa and /ecp are now being redirected to AD FS.
5 comments:
Great article!
Encountered exactly the same issue and it worked.
You sir are awesome. This is exactly what I needed.
Saved my bacon. Easy to find article that outlined my situation and detailed instructions to fix. Doesn't get any better than this. Thank you so much!
Huh, I had no idea this had to be done manually. I figured Exchange handled it's own certs.
EAC error lead me straight this page and these were very clear and precise powershell instructions.
Many thanks!
Terence! Thank you! You just saved our bacon! Very easy to follow instructions and it resolved our issue!
Post a Comment