Wednesday, February 14, 2018

ADFS : MSIS9642: The request cannot be completed

This is for Server 2016 (ADFS 4.0).

The full error is:

MSIS9642: The request cannot be completed because an id token is required but the server was unable to construct an id token for the current user.

You only get this error if you are using OpenID Connect with ADAL configured via Application Groups.

Our setup is:

User --> application --> external ADFS A --> internal ADFS B via HRD

We had used this model no problem with OWIN OIDC applications authenticating on both the internal and external ADFS.

However, on the applications that used ADAL, external authentication worked fine but trying the internal one threw the above error.

ADFS A is set up as a CP to ADFS B.

There's a good write-up here.

"The root cause of MSIS9642 is that the new OpenID Connect Application Group features in ADFS 2016 need to issue an access token to your application. This token must include the users identity. In order to issue the token the subsystem must understand which claim in the inbound claims is used to uniquely identify the user.

A new property called AnchorClaimType has been added to the Claim Provider Trust model."

Note that this property is not available on a RP trust.

The PowerShell needs to be run on the CP server i.e. ADFS A.

(Get-AdfsClaimsProviderTrust -Name "CP name").anchorclaimtype

This will be blank the first time. You can use any attribute that makes sense to uniquely identify the user. Typically, this would be sAMAccountName or UPN.

In our case, we had a custom claim so the command was:

Set-AdfsClaimsProviderTrust -TargetName "CP Trust" -AnchorClaimType "http://company/claims

and you can check this is correct by running the above Get-AdfsClaimsProviderTrust command again.

Remember that you need to pass-through this claim in the CP claims rules and the RP claims rules.


Monday, February 12, 2018

ADFS : Postman : Getting refresh token on Server 2016 - ADFS 4.0

Using Postman for the Authorisation Code Grant on Server 2016 (ADFS 4.0) is documented here.

Then someone asked me how to extend this to get a new access token using the refresh token.

Recall that the second part of the code grant is to send a code to the /token endpoint that returns an access token, a refresh token and an ID token.

To get a new access token, we use the same /token endpoint with the parameters above and the same refresh token that we received as described above.

This returns an access token and an ID token. It does not return another refresh token?

So back to the OAuth spec (RFC 6749) section:

6. Refreshing an Access Token

"If valid and authorized, the authorization server issues an access token as described in Section 5.1. If the request failed verification or is invalid, the authorization server returns an error response as described in Section 5.2.

The authorization server MAY issue a new refresh token, in which case the client MUST discard the old refresh token and replace it with the new refresh token.

The authorization server MAY revoke the old refresh token after issuing a new refresh token to the client. If a new refresh token is issued, the refresh token scope MUST be identical to that of the refresh token included by the client in the request."

So that is correct.

Note that you can use this refresh token over and over again until it expires and each time you will get a new access token.

There's a good write-up here around configuring the refresh token timeouts etc.

It revolves around the PowerShell command:

Get-AdfsRelyingPartyTrust |fl Name, IssueOAuthRefreshTokensTo, AlwaysRequireAuthentication, TokenLifetime

Name                        : RP Name
IssueOAuthRefreshTokensTo   : AllDevices
AlwaysRequireAuthentication : False
TokenLifetime               : 960