OAuth2 | TsgcHTTP_OAuth2_Client

This component allows to handle flow between client and the other roles, basically, when you set Active := True, opens a new Web Browser and requests user grant authorization, if successful, authorization server sends a token to application which is processed and with this token, client can connect to resource server. This component, starts a simple HTTP server which handles authorization server responses and uses an HTTP client to request Access Tokens.

 

GrantType

 

Client supports 2 types of Authorization:

 

auth2Code: It's used to perform authentication and authorization in the majority of application types, including single page applications, web applications, and natively installed applications. The flow enables apps to securely acquire access_tokens that can be used to access resources secured, as well as refresh tokens to get additional access_tokens, and ID tokens for the signed in user.

 

 

auth2CodePKCE: it's the same authentication flow than auth2Code with PKCE enabled. PKCE (Proof Key for Code Exchange) is a security extension for OAuth 2.0, designed to enhance the security of authorization flows for native and single-page applications. It mitigates the risk of interception attacks, especially in public clients where the authorization code might be exposed to interception in transit. Usually this option is used in native and mobile apps.

 

auth2ClientCredentials: This type of grant is commonly used for server-to-server interactions that must run in the background, without immediate interaction with a user. These types of applications are often referred to as daemons or service accounts.

 

 

LocalServerOptions

 

When a client needs a new Access Token, automatically starts an HTTP server to process response from Authorization server. This server is transparent for user and usually works in localhost. By default uses port 8080 but you can change if needed.

 

 

AuthorizationServerOptions

 

Here you must set URL for Authorization and Acces Token, usually these are provided in API specification. Scope is a list of all scopes requested by client. Example:

 

 

OAuth2Options

 

ClientId is a mandatory field which informs server which is the identification of client. Check your API specification to know how get a ClientId. The same applies for client secret.

Sometimes, server requires a user and password to connect using Basic Authentication, if this is the case, you can setup this in Username/Password fields. Example:

 

 

HTTPClientOptions

 

Here you can customize the Client Options when connects to HTTP Server to request a new token.

 

    TLSOptions: if TLS enabled, here you can customize some TLS properties.

 

ALPNProtocols: list of the ALPN protocols which will be sent to server.

RootCertFile: path to root certificate file.

CertFile: path to certificate file.

KeyFile: path to certificate key file.

Password: if certificate is secured with a password, set here.

VerifyCertificate: if certificate must be verified, enable this property.

VerifyDepth: is an Integer property that represents the maximum number of links permitted when verification is performed for the X.509 certificate.

Version: by default uses TLS 1.0, if server requires a higher TLS version, here can be selected.

IOHandler: select which library you will use to connection using TLS.

iohOpenSSL: uses OpenSSL library and is the default for Indy components. Requires to deploy openssl libraries for win32/win64.

iohSChannel: uses Secure Channel which is a security protocol implemented by Microsoft for Windows, doesn't require to deploy openssl libraries. Only works in Windows 32/64 bits.

OpenSSL_Options: allows defining which OpenSSL API will be used.

APIVersion: allows defining which OpenSSL API will be used.

oslAPI_1_0: uses API 1.0 OpenSSL, it's latest supported by Indy

oslAPI_1_1: uses API 1.1 OpenSSL, requires our custom Indy library and allows using OpenSSL 1.1.1 libraries (with TLS 1.3 support).

oslAPI_3_0: uses API 3.0 OpenSSL, requires our custom Indy library and allows using OpenSSL 3.0.0 libraries (with TLS 1.3 support).

LibPath: here you can configure where are located the openSSL libraries

oslpNone: this is the default, the openSSL libraries should be in the same folder where is the binary or in a known path.

oslpDefaultFolder: sets automatically the openSSL path where the libraries should be located for all IDE personalities.

oslpCustomFolder: if this is the option selected, define the full path in the property LibPathCustom.

LibPathCustom: when LibPath = oslpCustomFolder define here the full path where are located the openSSL libraries.

UnixSymLinks: enable or disable the loading of SymLinks under Unix systems (by default is enabled, except under OSX64):

oslsSymLinksDefault: by default are enabled except under OSX64 (after MacOS Monterey fails trying to load the library without version.).

oslsSymLinksLoadFirst: Load SymLinks and do before trying to load the version libraries.

oslsSymLinksLoad: Load SymLinks after trying to load the version libraries.

oslsSymLinksDontLoad: don't load the SymLinks.

SChannel_Options: allows to use a certificate from Windows Certificate Store.

CertHash: is the certificate Hash. You can find the certificate Hash running a dir command in powershell.

CertStoreName: the store name where is stored the certificate. Select one of below:

scsnMY (the default)

scsnCA

scsnRoot

scsnTrust

CertStorePath: the store path where is stored the certificate. Select one of below:

scspStoreCurrentUser (the default)

scspStoreLocalMachine

 

    LogOptions: if a filename is set, it will save a log of HTTP requests/responses of the HTTP client

 

 

OnBeforeAuthorizeCode

This is the first event, it's called before client opens a new Web Browser session. URL parameter can be modified if needed (usually not necessary).


void OnOAuth2BeforeAuthorizeCode(TObject Sender, ref string URL, ref bool Handled)
{
  DoLog("BeforeAuthorizeCode: " + URL);
}	

OnAfterAuthorizeCode

After a successful Authorization, server redirects the response to internal HTTP server, this response informs to client about Authorization code (which will be use later to get Access Token), state, scope...


void OnOAuth2AfterAuthorizeCode(TObject Sender, const string Code, const string State, const string Scope, 
  const string RawParams, ref bool Handled)
{
  DoLog("AfterAuthorizeCode: " + Code);
}

OnErrorAuthorizeCode

If there is an error, this event will be raised with information about error.


void OnOAuth2ErrorAuthorizeCode(TObject Sender, const string Error, const string Error_Description, 
  const string Error_URI, const string State, const string RawParams)
{
  DoLog("ErrorAuthorizeCode: " + Error + " " + Error_Description);
}

OnBeforeAccessToken

After get an Authorization Code, client connects to Authorization Server to request a new Access Token. Before client connects, this event is called where you can modify URL and parameters (usually not needed).


void OnOAuth2BeforeAccessToken(TObject Sender, ref string URL, ref string Parameters, 
  ref bool Handled);
{
  DoLog("BeforeAccesToken: " + URL + " " + Parameters);
}

OnAfterAccessToken

If server accepts client requests, it releases a new Access Token which will be used by client to get access to resources server.


void OnOAuth2AfterAccessToken(TObject Sender, const string Access_Token, const string Token_Type, 
  const string Expires_In, const string Refresh_Token, const string Scope, const string RawParams, ref bool Handled);
{
  DoLog("AfterAccessToken: " + Access_Token + " " + Refresh_Token + " " + Expires_In);
}

OnErrorAccessToken

If there is an error, this event will be raised with information about error.


void OnOAuth2ErrorAccessToken(TObject Sender, const string Error, const string Error_Description, 
  const string Error_URI, const string RawParams)
{
  DoLog("ErrorAccessToken: " + Error + " " + Error_Description);
}

OnBeforeRefreshToken

Access token expire after some certain time. If Authorization server releases a refresh token plus access token, client can connect after token has expires with a refresh token to request a new access token without the need of user Authenticates again with own credentials. This event is called before client requests a new access token.


void ONOAuth2BeforeRefreshToken(TObject Sender, ref string URL, ref string Parameters, ref bool Handled)
{
  DoLog("BeforeRefreshToken: " + URL + " " + Parameters);
}

OnAfterRefreshToken

If server accepts client requests, it releases a new Access Token which will be used by client to get access to resources server.


void OnOAuth2AfterRefreshToken(TObject Sender, const string Access_Token, const string Token_Type, 
  const string Expires_In, const string Refresh_Token, const string Scope, const string RawParams, ref bool Handled);
{
  DoLog("AfterRefreshToken: " + Access_Token + " " + Refresh_Token + " " + Expires_In)
}

OnErrorRefreshToken

If there is an error, this event will be raised with information about error.


void OnOAuth2ErrorRefreshToken(TObject Sender, const string Error, const string Error_Description, 
  const string Error_URI, const string RawParams)
{
  DoLog("ErrorRefreshToken: " + Error + " " + Error_Description);
}

OnHTTPResponse

This event is called before HTTP response is sent after a successful Access Token.


void OnOAuth2HTTPResponse(TObject Sender, ref int Code, ref string Text, ref bool Handled)
{
  Code = 200;
  Text = "Successful Authorization";
}

OAuth2 Code Example

Example of use to connect to Google Gmail API using OAuth2.  


oAuth2 = new TsgcHTTP2_OAuth2.Create();
oAuth2.LocalServerOptions.Host = "127.0.0.1";
oAuth2.LocalServerOptions.Port = 8080;
oAuth2.AuthorizationServerOptions.AuthURL = "https://accounts.google.com/o/oauth2/auth";
oAuth2.AuthorizationServerOptions.Scope = "https://mail.google.com/";
oAuth2.AuthorizationServerOptions.TokenURL = "https://accounts.google.com/o/oauth2/token";
oAuth2.OAuth2Options->ClientId = "180803918357-eqjtn20gqfhcs6gjkebbrrenh022mqqc.apps.googleusercontent.com";
oAuth2.OAuth2Options->ClientSecret = "_by0iYYrvVHxC2Z8TbtNEYQN";
   
void OnOAuth2AfterAccessToken(TObject Sender, const string Access_Token, const string Token_Type, 
  const string Expires_In, const string Refresh_Token, const string Scope, const string RawParams, ref bool Handled)
{
// write your code here     
}
 
oAuth2->OnAfterAccessToken = OnOAuth2AfterAccessToken;
oAuth2->Start();