public ActionResult Token() { ActionResult actionResult; if (!Request.Headers.AllKeys.Contains("Authorization")) { actionResult = TokenErrorJson("invalid_client", "The request is missing the Authorization header."); } else { try { TokenRequest tokenRequest = TokenRequest.Load(Request.Headers["Authorization"], Request.Form); if (string.IsNullOrEmpty(tokenRequest.GrantType)) { actionResult = TokenErrorJson("invalid_request", "The request is missing the 'grant_type' parameter."); } else if (tokenRequest.GrantType != "authorization_code") { actionResult = TokenErrorJson("unsupported_grant_type", $"The grant_type '{tokenRequest.GrantType}' is not supported. The only supported grant_type is 'authorization_code'."); } else if (string.IsNullOrEmpty(tokenRequest.Code)) { actionResult = TokenErrorJson("invalid_request", "The request is missing the 'code' parameter."); } else if (string.IsNullOrEmpty(tokenRequest.RedirectUri)) { actionResult = TokenErrorJson("invalid_request", "The request is missing the 'redirect_uri' parameter."); } else { Database.RegisteredClient registeredClient = Database.RegisteredClients.SingleOrDefault(rc => rc.Id == tokenRequest.ClientId); if (registeredClient == null || registeredClient.Secret != tokenRequest.ClientSecret) { actionResult = TokenErrorJson("invalid_client", "Invalid client ID or secret."); } else { Guid authorizationCode = Guid.Parse(tokenRequest.Code); Database.IssuedAuthorization issuedAuthorization; bool authorizationCodeExists = Database.IssuedAuthorizations.TryRemove(authorizationCode, out issuedAuthorization); if (!authorizationCodeExists) { actionResult = TokenErrorJson("invalid_grant", "Authorization code is invalid or was previously used."); } else if (issuedAuthorization.ClientId != tokenRequest.ClientId) { actionResult = TokenErrorJson("invalid_grant", "Authorization code was issued to another client."); } else if (issuedAuthorization.RedirectionUri != tokenRequest.RedirectUri) { actionResult = TokenErrorJson("invalid_grant", "redirect_uri of the token request does not match redirect_uri of the authorization request."); } else if ((DateTime.UtcNow - issuedAuthorization.TimeIssued) > AUTHORIZATION_CODE_VALIDITY_PERIOD) { actionResult = TokenErrorJson("invalid_grant", "Authorization code is expired."); } else { DateTime currentUtcTime = DateTime.UtcNow; var idToken = new IdToken( iss: Configuration.ISSUER_IDENTIFIER, sub: issuedAuthorization.UserId, aud: new string[] { registeredClient.Id }, exp: currentUtcTime.Add(ID_TOKEN_VALIDITY_PERIOD), iat: currentUtcTime, nonce: issuedAuthorization.Nonce); string idTokenJws = idToken.GetJws(registeredClient.Secret); SuccessfulTokenResponse successfulTokenResponse = new SuccessfulTokenResponse( tokenType: "Bearer", accessToken: "Dummy", // Access token is not used here but it is required by the OAuth 2.0 specifications. idToken: idTokenJws); actionResult = Content(successfulTokenResponse.GetResponseJson(), "application/json"); } } } } catch (TokenRequestParsingException ex) { actionResult = TokenErrorJson("invalid_request", ex.Message); } } return(actionResult); }