The login screen is the one part of a business application that every customer has an opinion about. Can we sign in with our Entra ID account. Does it support passkeys. Our auditors want two-factor. Our users are in Active Directory, why do they need another password. And the mail your application sends stopped working the day Microsoft 365 refused the password in the SMTP settings.
Each of those questions is a protocol with its own specification, its own XML or ASN.1, and its own ways to be almost right. The new Enterprise authentication components answer them as Delphi components. They ship in the Enterprise and All-Access editions of sgcWebSockets and in the sgcAuth pack, and the same components are part of sgcWebSockets .NET.
Passkeys, the Way Users Expect Them
The WebAuthn server now covers what people actually mean when they say passkeys:
- Usernameless sign-in. The user presses one button, the browser offers the passkeys it holds for your site, and the account is identified by the credential. Nothing to type.
- Autofill. Passkeys appear in the browser's own suggestion list on the user name field, next to saved passwords, so a login page can offer both while users move over.
- Several passkeys per user. One on the phone, one on the laptop, one hardware key in a drawer for the day both are lost.
- Synced passkey detection. The server tells a passkey that the platform backs up and syncs from one bound to a single device, so your policy can treat them differently.
- Your own database. Passkeys live next to your users table, not in a file the component owns.
SAML Single Sign-On
Large customers do not want their staff to have an account in your application. They want them to sign in with the identity provider the company already runs. TsgcSAMLServiceProvider makes your application a SAML 2.0 service provider for Entra ID, Okta, AD FS, Google Workspace and Keycloak. The identity provider does the login, your application receives an assertion, and the signature on that assertion is validated before you ever see a user name.
Active Directory and LDAP Login
For the application that runs inside the company network, the users already have a password: their Windows one. TsgcLDAPClient checks a user name and password against Active Directory or any LDAP directory, over LDAPS or StartTLS so the password never crosses the network in clear. Set Security to ldapsecLDAPS or ldapsecStartTLS and call Authenticate.
Knowing who the user is only answers half the question. GetUserGroups returns the groups the account belongs to, nested groups included, so “is this user an invoice approver” is one call instead of a recursive search you write and debug yourself.
Two-Factor Codes From an Authenticator App
TsgcTOTPAuthenticator produces and checks the six digit codes of Google Authenticator, Microsoft Authenticator and every other TOTP app. Enrolment is a secret and a URI you show as a QR code. Sign-in is one call:
uses
sgcAuth_TOTP, sgcBase_Helpers;
var
oTOTP: TsgcTOTPAuthenticator;
vSecret, vURI: string;
vLastStep: Int64;
begin
oTOTP := TsgcTOTPAuthenticator.Create(nil);
try
oTOTP.Issuer := 'MyApp';
// enrolment: store vSecret with the user, show vURI as a QR code
vSecret := oTOTP.GenerateSecret;
vURI := oTOTP.GetProvisioningURI('john@example.com', vSecret);
// sign-in: vLastStep is the last step accepted for this user, -1 the first time
vLastStep := -1;
if oTOTP.VerifyCode(vSecret, txtCode.Text,
StrToInt64(GetDateTimeUnix(Now)), vLastStep) then
ShowMessage('Signed in') // save vLastStep, this code is now spent
else
ShowMessage('Wrong, expired or already used');
finally
oTOTP.Free;
end;
end;
That overload is the replay protection: a code that has already been accepted is refused, even inside its own thirty seconds, so a code read over someone's shoulder is worth nothing once it has been used. For the day the phone is lost, GenerateRecoveryCodes fills a list with one-time recovery codes. Store them the way you store passwords.
OpenID Connect Sign-In
TsgcHTTP_OIDC_Client signs users in with any OpenID Connect provider. It reads the provider's discovery document, so the configuration is an issuer URL and a client ID rather than a list of endpoints copied by hand. It validates the ID token it receives, and the same signing keys validate the bearer tokens that reach your own REST API, including tokens from Entra ID multi-tenant applications, where every customer's tenant signs with its own issuer.
OAuth2 for Microsoft 365 and Gmail Mail
Microsoft 365 and Gmail expect OAuth2, not a password, from SMTP, IMAP and POP3. TsgcMailOAuth2 obtains the access token, refreshes it, and builds the XOAUTH2 string your SMTP, IMAP or POP3 session signs in with. Choose the provider and the protocols, give it your client ID, and keep the refresh token when OnTokensChanged fires. A service or a console application with no browser can use the device code flow instead.
Try the Demos
Every component has a runnable demo in Demos\26.Authentication:
01.Passkeys, usernameless sign-in and autofill in the browser.02.TOTP, enrolment with a QR code, verification and recovery codes.03.SAML_ServiceProvider, single sign-on against your identity provider.04.OpenID_Connect, sign-in and token validation.05.LDAP_ActiveDirectory, login and group membership.06.Mail_OAuth2, sending mail from Microsoft 365 or Gmail with OAuth2.
Documentation
- Passkeys
- TsgcSAMLServiceProvider
- TsgcLDAPClient
- TsgcTOTPAuthenticator
- TsgcHTTP_OIDC_Client
- TsgcMailOAuth2
Where to Get Them
The components are included in the Enterprise and All-Access editions of sgcWebSockets, for Delphi, C++ Builder and .NET. If you only need authentication, the sgcAuth pack has them on their own. They are additive: nothing changes in an existing application until you drop one on a form.
Read Next
Watch It
There is a short video, “Delphi login with passkeys, SAML SSO, Active Directory LDAP and TOTP 2FA”, on the eSeGeCe channel.
Questions, feedback or help wiring this into your login page? Get in touch. You will get a reply from the people who wrote the code.
