Active Directory Federation Service (ADFS) is a federated identity service using Active Directory (AD) as the identity provider (IdP).

Microsoft initially created ADFS to enable single sign-on for windows based applications using Active Directory (AD) as the identity service.  Users that have authenticated once via AFDS can share the authentication with other ADFS enabled applications (when configured).

Starting with Windows Server 2012 R2, ADFS was extended to support additional authentication protocols such as SAML2.0, OAuth, OAUTH2.0 and OpenIdConnect to promote ADFS' compatibility with other applications.

ADFS 3.0 for OAuth JWT

OAUTH 2.0 defines various authorization grants, client and token types but ADFS 3.0 only supports a subset of these including Authentication Code flow. Microsoft increased the support for additional OAUTH2.0 protocols and frameworks such as OpenIDConnect (OIDC) with Windows Server 2016 ADFS 4.0. (source)

Grant type ADFS 2.0 ADFS 3.0
Authorization code grant Y(es) Y
Implicit grant N(o) Y
Resource owner credentials N Y
Client credentials N Y
Client types ADFS 2.0 ADFS 3.0
Public Client N Y
Confidential Client N N

In addition, Microsoft's client-side authentication library known as MSAL.js does not have out-of-box client libraries that support SPA applications for OAUTH2 Authentication Code flow. Though some client authentication frameworks such as adal.js will work with ADFS 3.0.

The following are steps needed to obtain a valid access_token from ADFS using the OAuth authentication Code flow (source):

  1. Resource owner (RO) requests authentication from the OAUTH client application.
  2. OAUTH client application redirects resource owner to ADFS credentials login page.
  3. Authenticated RO gets redirected with a token that can be used to retrieve a linked access_token.
  4. Client application requests access_token using the linked token.
Depiction of the authentication flow between the user, user-agent (SPA), web-api and the authorization server (ADFS)  source

source - protecting .Net Core SPA application
source - setup ADFS to issue OAuth tokens
source - AFDS and OAuth2 possible ? Demo: setup ADFS 3.0 to use OAUTH 2.0
source - jwt support for adfs

Demo: using ADFS 3.0 to secure SPA web application

This demo will cover how to setup ADFS to use OAUTH2.0 for authentication using the Authorization Code flow.  The application we are securing consists of a React front end and a .Net Core 2 API. The API will be using JwtBearerAuthentication to validate the JWT generated from ADFS federated identity.

Below is an overview of the key steps involved:

1) Authorization request
- React (font-end UI) redirects user to ADFS authorization end point

GET /adfs/oauth2/authorize?response_type=code&client_id=application_identifier&resource=relying_party_trust_identifier&redirect_uri=application_callback_url

2) User login challenge
- ADSF presents a login screen where the user can log in with credentials
- Once the user is authenticated, ADFS issues session cookie and redirects the user back to React application along with the token.

HTTP/1.1
Host: adfs_sever_hostname

3) Authorization Grant
- React extracts code token

HTTP/1.1 302 Found
Location: application_callback_url?code=autorization_code

4)  Access token request (via .Net Core API)
- Using the extracted code token we request an access_token

POST /adfs/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: adfs_sever_hostname
Content-Length: length_of_content

grant_type=authorization_code&client_id=application_identifier&redirect_uri=application_callback_url&code=autorization_code
Using React to request access_token will likely not work if the client is a SPA running on a different (sub)domain than ADFS due to CORS.  (source)
Two options:
1. Enable CORS on ADFS (requires a web server that supports CORS)
2. Create a new endpoint proxy on .Net Core API to request access_token to bypass CORS issue.

5)  ADFS returns the access_token to (.Net Core API)

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
    "access_token":access_token,
    "token_type":"bearer",
    "expires_in":6000
}

source - ADFS 3.0 and OAuth example

ADFS configuration

  1. Add Replying Party Trust (RPT)
  • Follow the instructions
  • Leave encryption details blank (ADFS 3.0 does not support)
  • Leave WS and SAML configuration blank (Only OAuth needed)
  • Add RPT Identifier(user application domain name)
  1. Add AdfsClient to RT
  2. Enable JWT for RT
  3. Add AD claims (Optional)
# Check if RPT name is unique
Get-AdfsRelyingPartyTrust -Name "rpt_application_name"

# Add Adfs client to RPT (ClientId=generated GUID)
Add-AdfsClient -RedirectUri "http://example.com/token" -ClientId "00000000-0000-0000-0000-000000000000" -Name "any_client_name"

# Check the created Adfs client
Get-AdfsClient -Name "any_client_name"

# Enable JWT for RPT
Set-AdfsRelyingPartyTrust -TargetName "rpt_application_name" -EnableJWT $true
ADFS 3.0 does not support secrets or token encryption/decryption for OAUTH2. Multiple Adfs Clients can be associated with one relying party trust, each representing a different application. The identifier should be unique across all relying parties.

source - configuring ADFS for OAUTH
source - WPF example using OAUTH with ADFS 3.0
source - setup relying party trust
source - setup adfs 3.0 for OAuth2