Reputation: 3364
I successfully set up an ADFS 4.0 instance (Windows Server 2016) which I intend to use to authenticate and authorize the users of a single-page application towards a WebApi.
I pretty much followed this tutorial: https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/single-page-application-with-ad-fs .. which is modifying a sample that uses Azure Active Directory.
Now.. all seems to work fine, I can get a basic JWT token from the /oauth2/authorize
endpoint:
{
"aud": "d668d637-7fd4-45ef-9eab-46fee230dcbc",
"iss": "https://fs.contoso.com/adfs",
"iat": 1494341035,
"exp": 1494344635,
"auth_time": 1494341035,
"nonce": "c91e3f78-c31a-402e-a685-8d1586915227",
"sub": "Rl7sOj0nDbgh8BVWZegrkvgAKaB/SwNuEbmORcWcae4=",
"upn": "[email protected]",
"unique_name": "CONTOSO\\JohnDoe"
}
The token from AzureAD contained more properties, particularly family_name
and given_name
. But I was also hoping to add explicit group claims to the token. I thought I should be able to make this happen by setting the 'Issuance Transform Rules' correctly in the Web application Properties ( Application Groups -> MyApp -> MyApp - WebApplication -> Properties). However, it seems no matter what I do, nothing seems to have any effect on the properties contained in the JWT returned from the endpoint. I always get exactly the same token structure.
I am not really sure how the 'Outgoing Claims' map to the token properties as nothing except the 'UPN' and the 'unique name' seems to be transferred. Any pointers what I may be doing wrong here?
Upvotes: 2
Views: 7264
Reputation: 3364
As indicated in nzpcmad's answer, it appears that custom claims in the id_token using the default URL-parameter-encoded GET redirect is simply not supported. The reason for this may be that there is an URL length limit, but I find that quite questionable.
Anyway, apparently this restriction does not apply when the token is returned in a POST redirect. That's also why people describe it working just fine for MVC applications.
So I was able to work around the problem by redirecting the response to a backend API endpoint (POST), which just redirects it to the frontend (SPA) again, but as a GET request with URL-endcoded parameters:
public class LoginController : ApiController
{
[HttpPost]
[Route("login")]
public HttpResponseMessage Login(FormDataCollection formData)
{
var token = formData["id_token"];
var state = formData["state"];
var response = Request.CreateResponse(HttpStatusCode.Moved);
var frontendUri = ConfigurationManager.AppSettings["ad:FrontendUri"];
response.Headers.Location = new Uri($"{frontendUri}#id_token={token}&state={state}");
return response;
}
}
Note that to change the response method from GET to POST, one simply has to add &response_mode=form_post
to the OAuth request URL.
Upvotes: 7
Reputation: 46720
Windows Server 2016 is ADFS 4.0.
SPA uses OAuth implicit flow and there are a number of posts around this suggesting that this flow doesn't allow extra claims, especially if you are using ADAL.
e.g. ADFS 4.0, Adal JS - No claims.
Upvotes: 1