How to authenticate with SAML in ASP.NET Core and C#

How to authenticate with SAML in ASP.NET Core and C#

Learn how to authenticate with SAML in ASP.NET Core and C#.

Artur Gordashnikov

Thanks Nick for this great tutorial! One question: according the docks it should be possible to offload saml SP implementation to Okta. This way Asp.Net Core app will always work with OIDC only. What the difference in IdP, SP and Asp.Net Core configuration in this case? All my tries to make it work finished on SP (Okta) login page (after successful SAMLResponse assertion). The url looks like this:


This page doesn’t accept IdP user credentials, but if I login with SP user credentials it redirects me to desired app url.

Nick Gamb

Hi Artur! I am glad you liked it.

Yes, Okta is able to accept authorization from another OIDC IDP and then pass the user to a SAML SP that it is protecting.

If you follow this blog as is, you have the Okta to SAML SP aspect ready. Next you would need to go through this guide in Okta… and write a web application to be the OIDC IDP.

In the guide I linked to it describes the callback URL. That is the part that I think you need. The Callback URL is where your OIDC IDP needs to redirect the user back to. It would look like https://{domain}/oauth2/v1/authorize/callback.

The design would be for the user to start at the SAML SP and redirect to Okta for authentication (Or to navigate directly to the SAML application embed link), the user would select your OIDC IDP app as the authentication mechanism in Okta (or be required to use this factor only by default), and then the user would be directed off to your app to authenticate. Once your app sends the user to the Okta callback URL, Okta will allow the user to continue to the SAML SP. Okta is the IDP for the SAML SP, so it drives the authentication requirements. Your OIDC IDP app is set up as an IDP to Okta and Okta delegates auth to it as the auth requirement for the user.

I hope that helps!

Boris Meerovich

Thanks for the tutorial. It took me 10 min to configure a new app with the tutorial and all looks ok. When I tried to integrate the SAML2 to the existing client-server app, I got the following error:
Access to XMLHttpRequest at '… (redirected from ‘http://localhost:9000/APP_URL’) from origin ‘http://localhost:9000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

This is existing Angular app with c# .net core API.

My ‘login’ method returned code 302 to redirect to the OKTA server and the I’ve got an error…
Any idea what could be a problem?

Nick Gamb

Hi Boris,

I think this is because you are triggering Okta’s CORS protections. From your Okta Admin UI can you go to API > Trusted Origins (If using the Classic UI it would be under Security > API > Trusted Origins) and add “http://localhost:9000” as a Trusted Origin (make sure to check “Redirect” at the bottom when adding.)? This should add your site to an approved list for redirects and resolve the issue for you. Let me know!

Boris Meerovich

I’ll try to do it, but for now I just created a new a tag with href to my login method and it’s already redirects me correct.

Nick Gamb

Great! Let me know if any other questions come up!

Dan Lee BTS

Thanks Nick for this excellent tutorial!

Our .Net Web App needs to support both SAML and OIDC for SSO
From a SAML perspective, our App would be a service provider

Every customer integrating with our Web App would bring in their own IdP and we need to configure SSO with them

Because we are Azure centric, we toyed with the idea of using Azure AD B2C for securing our Web App
But, AAD B2C supports Identity Provider initiated sign on ONLY IF Identity Provider is Azure AD B2C

We are now ideating on using Okta for securing our Service Provider App

So we were wondering how to bring in OIDC as well in this sample code
Is that possible?

NOTE : Web App would always be accessed AFTER user’s authenticate against their IdP, e.g IdP initiated SAML Flow


Hi Nick Thanks for the Help,
But this is not working for the Logout Functionality.
Please help me for that.

Boris Meerovich

Hi Nick,
How can I define a refresh token logic in your example to make “silent” login after the session was expired?

Peter B

Great tutorial!
I was using .NET 5 (without even realizing it; Visual Studio 2019 just does so by default now) and with that, the given v4.0.8 of ITfoxtec components will not work. I got lots of NullReference exceptions when the SAML responses were being parsed…
Fortunately there now is v4.1.1 which does work. I might help if you could make a note of this it in that area of the blog post, so future visitors will not have to go through this again.

Sudarshan T


Jaish Mathews

Thanks for this. I could able to login with SAML with a Blazor server application too. One question is that Claims aren’t returning the OKTA groups belongs to the logged-in user. I assigned groups to the app inside OKTA. But those groups are not returning as part of Claim. Once I used OpenID, there’s an option of "Groups claim filter "inside OKTA. But I couldn’t see it for SAML? Any lead here?


Thanks Peter.
I had the same problem. I solved removing both ITfoxtec packages, and adding them with version 4.1.1. This work like a charm.

dotnet remove package ITfoxtec.Identity.Saml2.MvcCore
dotnet remove package ITfoxtec.Identity.Saml2

dotnet add package ITfoxtec.Identity.Saml2 --version 4.1.1
dotnet add package ITfoxtec.Identity.Saml2.MvcCore --version 4.1.1

Rahul Jadhav

Hi Nick, The nice explanation of the OKTA integration!
One question - If the front end is Angular 8 and Middleware is Web API 2.0 then how to implement the OKTA SAML authentication? if you have any articles or example on this, Kindly share.


I was experiencing the same issue, then i found that for SAML you have to configure the app (in okta dashboard) to return the groups.…

what’s really great about this approach is that you have control over which groups you want to return. so if you have groups like “VPN Users”, “Accounting”, along with app specific groups like “NinjaApp Admin”, “NinjaApp Basic”, etc, you can configure the app to only return the groups that start with NinjaApp. that way your NinjaApp doesn’t get corporate information like that the user is in the VPN group.

Rahul Jadhav

Hi Boris,
The CORS error occurs in the project. The flow of the app is the angular app call the web API login method binding the SAML request after that Ideal approach is to see the OKTA login screen but not due to the CORS issue. Please tell me, how did you handle the CORS issue? My web site added into Trusted Origin of OKTA.

James Gardner

Agree with the other that this is a great tutorial with easy to follow code. I run the project and click “login” and get the following error in the Startup.cs file . . . google was no help with this. Is there a way to access the metadata locally.

James Gardner

I figured it out. I published the metadata file to me own server. — Thanks


Hello. I was able to follow the sample quite easily and got everything working. Then I tried to add to a real application where I am using ASP.NET Identity framework as well. It seems that once I tried adding that, the user identity wasn’t set on subsequent pages. Is the ITFoxtec library compatible with the identity framework?