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 to define which OpenSSL API will be used.

APIVersion: allows to define 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 to use 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 to use 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).


procedure OnOAuth2BeforeAuthorizeCode(Sender: TObject; var URL: string; var Handled:
Boolean);
begin
  DoLog('BeforeAuthorizeCode: ' + URL);
end;

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...


procedure OnOAuth2AfterAuthorizeCode(Sender: TObject; const Code, State, Scope, RawParams: string; 
  var Handled: Boolean);
begin
  DoLog('AfterAuthorizeCode: ' + Code);
end;

OnErrorAuthorizeCode

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


procedure OnOAuth2ErrorAuthorizeCode(Sender: TObject; const Error, Error_Description, Error_URI, State, 
  RawParams: string);
begin
  DoLog('ErrorAuthorizeCode: ' + Error + ' ' + Error_Description);
end;

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).


procedure OnOAuth2BeforeAccessToken(Sender: TObject; var URL, Parameters: string; 
  var Handled: Boolean);
begin
  DoLog('BeforeAccesToken: ' + URL + ' ' + Parameters);
end;

OnAfterAccessToken

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


procedure OnOAuth2AfterAccessToken(Sender: TObject; const Access_Token, Token_Type, Expires_In, 
  Refresh_Token, Scope, RawParams:
    string; var Handled: Boolean);
begin
  DoLog('AfterAccessToken: ' + Access_Token + ' ' + Refresh_Token + ' ' + Expires_In);
end;

OnErrorAccessToken

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


procedure OnOAuth2ErrorAccessToken(Sender: TObject; const Error, Error_Description, Error_URI, 
  RawParams: string);
begin
  DoLog('ErrorAccessToken: ' + Error + ' ' + Error_Description);
end;

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.


procedure ONOAuth2BeforeRefreshToken(Sender: TObject; var URL, Parameters: string; var Handled: Boolean);
begin
  DoLog('BeforeRefreshToken: ' + URL + ' ' + Parameters);
end;

OnAfterRefreshToken

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


procedure OnOAuth2AfterRefreshToken(Sender: TObject; const Access_Token, Token_Type, Expires_In, 
  Refresh_Token, Scope, RawParams: string; var Handled: Boolean);
begin
  DoLog('AfterRefreshToken: ' + Access_Token + ' ' + Refresh_Token + ' ' + Expires_In);
end;

OnErrorRefreshToken

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


procedure OnOAuth2ErrorRefreshToken(Sender: TObject; const Error, Error_Description, Error_URI, 
  RawParams: string);
begin
  DoLog('ErrorRefreshToken: ' + Error + ' ' + Error_Description);
end;

OnHTTPResponse

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


procedure OnOAuth2HTTPResponse(Sender: TObject; var Code: Integer; var Text: string; var Handled: Boolean);
begin
  Code := 200;
  Text := 'Successful Authorization';
end;

OAuth2 Code Example

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


oAuth2 := TsgcHTTP2_OAuth2.Create(nil);
oAuth2.LocalServerOptions.Host := '127.0.0.1';
oAuth2.LocalServerOptions.Port := 8080;
oAuth2.AuthorizationServerOptions.AuthURL := 'https://accounts.google.com/o/oauth2/auth';
oAuth2.AuthorizationServerOptions.Scope.Add('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';
  
procedure OnOAuth2AfterAccessToken(Sender: TObject; const Access_Token, Token_Type, Expires_In, 
  Refresh_Token, Scope, RawParams: string; var Handled: Boolean);
begin
  <...>
  
  <...>
end;
oAuth2.OnAfterAccessToken := OnOAuth2AfterAccessToken;
oAuth2.Start;

 

Using TWebBrowser

You can use a TWebBrowser (if the webpage supports it) instead of regular WebBrowser like Chrome, Firefox or Edge.

Use the event OnBeforeAuthorizeCode to avoid opening a new WebBrowser session and use a TWebBrowser.

 


procedure OnBeforeAuthorizeCode(Sender: TObject; var URL: string; var Handled: Boolean);
begin
  Handled := True;
  WebBrowser1.Navigate(URL);
end;