OAuth 2.0 Authorization Code Grant
The Authorization Code Grant requests an authorization code that can be exchanged for an ID token and access token. Tokens are never exposed to the user agent, preventing interception. The flow requires the client to interact with the resource owner's user agent (typically a web browser) to complete authentication.
Authorization Code Grant Flow
The OAuth 2.0 Authorization Code Grant flow in EmpowerID:

Flow Steps
-
Initiate Authorization Request - Direct the user agent to the Authorization endpoint (
https://<EID Server>/oauth/v2/ui/authorize) with required parameters:response_type: Set tocodefor authorization code flowclient_id: Client application identifierscope: Space-separated list of permissions (e.g.,openid)redirect_uri: Callback URL for post-authentication redirect- Optional:
state(CSRF prevention) andnonce(replay attack mitigation)
-
User Authentication - The resource owner submits credentials via the authorization server's login form. Authentication methods include username/password, external identity providers, or multi-factor authentication.
-
Authorization Code Issued - The authorization server redirects to the
redirect_uriwith an authorization code and optionalid_tokenin the query parameters. -
Token Request - Exchange the authorization code for tokens via a back-channel request to the Token endpoint (
https://<EID Server>/oauth/v2/token) with:grant_type: Set toauthorization_codeclient_id: Client application identifierclient_secret: Client application secretcode: Authorization code from Step 3
-
Token Response - After validating credentials, the authorization code, and the
redirect_uri, the authorization server issues an access token and refresh token.
Authorization Code Grant
-
Send authorization request to
https://<EID Server>/oauth/v2/ui/authorizehttps://<EID Server>/oauth/v2/ui/authorize
?client_id=xxxxxxxxxxxxxxxxxx
&redirect_uri=https%3A%2F%2Ftestoauthapp.com%2FcallbackUrl
&response_type=code
&scope=openid
&state=xxxxxxxxxxxxxxxxxx
&nonce=xxxxxxxxxxxxxxxxxxRequest Parameter Required/Optional Description response_typerequired Set to codefor authorization code flow. Usecode id_tokenfor OpenID Connect.client_idrequired EmpowerID OAuth application client identifier redirect_urirequired Callback URL registered in the EmpowerID OAuth application scoperequired Space-separated permission list. Include openidfor OpenID Connect.stateoptional Random string for session maintenance and CSRF prevention nonceoptional Random string for request identification -
Authenticate using username/password or an external identity provider.
-
Authorization server redirects to
redirect_uriwith response parameters:https://testoauthapp.com/callbackUrl
?state=xxxxxxxxxxxxxxxxxx
&code=xxxxxxxxxxxxxxxxxx
&id_token=xxxxxxxxxxxxxxxxxxResponse Parameter Description stateSession value from client request codeAuthorization code from authorization server id_tokenIdentity token (OpenID Connect flow only) -
Exchange code for access token at
https://<EID Server>/oauth/v2/tokenhttps://<EID Server>/oauth/v2/token
?client_id={The Client ID of the OAuth app you registered in EmpowerID}
&client_secret={The Client Secret of the OAuth app you registered in EmpowerID}
&grant_type=authorization_code
&code=xxxxxxxxxxxxxxxxxxRequest Parameter Required/Optional Description grant_typerequired Set to authorization_codeclient_idrequired EmpowerID OAuth application client identifier client_secretrequired EmpowerID OAuth application client secret coderequired Authorization code from authorization server -
Token response:
{
"access_token": "xxxxxxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "xxxxxxxxxxxxxxxxxxxxxx",
"id_token": "xxxxxxxxxxxxxxxxxxxxxx",
"id": "xxxxxxxxxxxxxxxxxxxxxx"
}
Authorization Code Grant using .NET Client Library
-
Initialize
ClientSettingsandAuthorizationCodeGrant:var clientSettings = new ClientSettings(
"client_id",
"client_secret",
"redirect_uri",
"https://<EID Server>/oauth/v2/token",
"https://<EID Server>/oauth/v2/ui/authorize",
"https://<EID Server>/oauth/v2/tokeninfo",
"https://<EID Server>/oauth/v2/userinfo");
var handler = new AuthorizationCodeGrant(clientSettings); -
Build authorization request parameters using
BuildAuthorizationRequestPacket()://Generate random nonce and state
var nonce = Guid.NewGuid().ToString("N");
var state = Guid.NewGuid().ToString("N");
//Build parameters for "code" flow
var parameters = handler.BuildAuthorizationRequestPacket
(ParameterFormat.FormUrlEncoded, state, null, nonce, null);
//Build parameters for "code id_token" flow
var responseTypes = new List<ResponseType> { ResponseType.id_token };
var parameters = handler.BuildAuthorizationRequestPacket
(ParameterFormat.FormUrlEncoded, state, "openid", nonce, responseTypes);
//Generate redirect URL
var redirectUrl = string.Format("{0}?{1}", clientSettings.AuthorizeUrl, parameters);- In the callback method, extract
codeandstate, then request tokens:
public ActionResult AuthorizationCodeGrantResponse(AuthorizationResponseModel model)
{
AuthorizationResponseModel authorizationResponseModel = new AuthorizationResponseModel() {Code = "xxxxxxx", State = state};
AccessTokenResponseModel tokenResponseModel = null;
try
{
tokenResponseModel = handler.GetAccessToken<AccessTokenResponseModel>(
RequestMethod.POST,
ParameterFormat.FormUrlEncoded,
authorizationResponseModel,
false);
}
catch { //Handle error }
} - In the callback method, extract
Authorization Code Grant with PKCE (Proof Key for Code Exchange)
-
Send authorization request to
https://<EID Server>/oauth/v2/ui/authorizehttps://<EID Server>/oauth/v2/ui/authorize
?client_id=xxxxxxxxxxxxxxxxxx
&redirect_uri=https%3A%2F%2Ftestoauthapp.com%2FcallbackUrl
&response_type=code
&state=xxxxxxxxxxxxxxxxxx
&nonce=xxxxxxxxxxxxxxxxxx
&scope=openid
&code_challenge=xxxxxxxxxxxxxxxxxx
&code_challenge_method=S256Request Parameter Required/Optional Description response_typerequired Set to codefor authorization code flow. Usecode id_tokenfor OpenID Connect.client_idrequired EmpowerID OAuth application client identifier redirect_urirequired Callback URL registered in the EmpowerID OAuth application scoperequired Space-separated permission list. Include openidfor OpenID Connect.code_challenge_methodrecommended Transformation method: plainorS256. Defaults toplain.code_challengerequired Derived from code_verifier:
- plain:code_challenge = code_verifier
- S256:code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
See PKCE RFC for code verifier generation.stateoptional Random string for session maintenance and CSRF prevention nonceoptional Random string for request identification -
Authenticate using username/password or an external identity provider.
-
Authorization server redirects to
redirect_uriwith response parameters:https://testoauthapp.com/callbackUrl
?state=xxxxxxxxxxxxxxxxxx
&code=xxxxxxxxxxxxxxxxxx
&id_token=xxxxxxxxxxxxxxxxxxResponse Parameter Description stateSession value from client request codeAuthorization code from authorization server id_tokenIdentity token (OpenID Connect flow only) -
Exchange code for access token at
https://<EID Server>/oauth/v2/tokenhttps://<EID Server>/oauth/v2/token
?client_id={The Client ID of the OAuth app you registered in EmpowerID}
&client_secret={The Client Secret of the OAuth app you registered in EmpowerID}
&grant_type=authorization_code
&code=xxxxxxxxxxxxxxxxxx
&code_verifier=xxxxxxxxxxxxxxxxxxRequest Parameter Required/Optional Description grant_typerequired Set to authorization_codeclient_idrequired EmpowerID OAuth application client identifier client_secretrequired EmpowerID OAuth application client secret coderequired Authorization code from authorization server code_verifierrequired Code verifier from initial authorization request -
Token response:
{
"access_token": "xxxxxxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "xxxxxxxxxxxxxxxxxxxxxx",
"id_token": "xxxxxxxxxxxxxxxxxxxxxx",
"id": "xxxxxxxxxxxxxxxxxxxxxx"
}
Authorization Code Grant with PKCE using .NET Client Library
-
Initialize
ClientSettingsandAuthorizationCodeGrant:var clientSettings = new ClientSettings(
"client_id",
"client_secret",
"redirect_uri",
"https://<EID Server>/oauth/v2/token",
"https://<EID Server>/oauth/v2/ui/authorize",
"https://<EID Server>/oauth/v2/tokeninfo",
"https://<EID Server>/oauth/v2/userinfo");
var handler = new AuthorizationCodeGrant(clientSettings); -
Build authorization request with PKCE using
BuildAuthorizationRequestPacketWithPKCE()://Generate random nonce and state
var nonce = Guid.NewGuid().ToString("N");
var state = Guid.NewGuid().ToString("N");
//Generate code_verifier
var unreservedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_`";
Random random = new Random();
var code_verifier = new string(Enumerable.Repeat(unreservedChars, 43).Select(s => s[random.Next(s.Length)]).ToArray());
//Store code_verifier (e.g., in cookie)
CookieHelper.SetCookieData("OAuthCodeVerifier", code_verifier);
//Generate code_challenge (plain method)
//var code_challenge = code_verifier;
//var code_challenge_method = "plain";
//Generate code_challenge (S256 method)
var bytes = new SHA256CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(code_verifier));
var code_challenge = Convert.ToBase64String(bytes).Split('=')[0].Replace('+', '-').Replace('/', '_');
var code_challenge_method = "S256";
//Build parameters for "code" flow
var parameters = handler.BuildAuthorizationRequestPacketWithPKCE
(ParameterFormat.FormUrlEncoded, state, null, nonce, code_challenge, code_challenge_method, null);
//Build parameters for "code id_token" flow
//var responseTypes = new List<ResponseType> { ResponseType.id_token };
//var parameters = handler.BuildAuthorizationRequestPacketWithPKCE
//(ParameterFormat.FormUrlEncoded, state, "openid", nonce, code_challenge, code_challenge_method, responseTypes);
//Generate redirect URL
var redirectUrl = string.Format("{0}?{1}", clientSettings.AuthorizeUrl, parameters); -
In the callback method, extract
codeandstate, retrievecode_verifier, then exchange for tokens:public ActionResult AuthorizationCodeGrantWithPKCE(AuthorizationCodeGrantViewModel model)
{
AuthorizationResponseModel authorizationResponseModel = new AuthorizationResponseModel() {Code = "xxxxxxx", State = state};
//Retrieve stored code_verifier
var code_verifier = CookieHelper.GetCookieData("OAuthCodeVerifier");
var additionalParams = new Dictionary<string, string>();
additionalParams["code_verifier"] = code_verifier;
AccessTokenResponseModel tokenResponseModel = null;
try
{
tokenResponseModel = handler.GetAccessToken<AccessTokenResponseModel>(
RequestMethod.POST,
ParameterFormat.FormUrlEncoded,
authorizationResponseModel,
false,
null,
additionalParams);
}
catch { //Handle error }
}