Blog

SSO best practices

SSO is necessary if you want to sell to enterprise customers, but doing it well is hard. We gathered some best practices that can help you with that.


SSO is a must-have feature, whether you are targeting large enterprise deals or just want to remove the signup friction that causes your visitors to abandon your app. However, implementing SSO is a highly complicated project with serious consequences should you do it wrong—from temporary loss of service to full-blown data breaches.

In this article, we will review some important SSO best practices that you should always consider, whether you are implementing SSO in-house or using a third-party provider.

General best practices

We will start with a set of best practices that apply regardless of which protocol you use.

Proper session management

Once a user is authenticated, managing their sessions effectively is key both from a security and a user-experience perspective. Keep in mind the following best practices:

  • Limit sessions per user: Users should not open an excessive number of sessions at once, as this can be a security risk. For example, users can be limited to three concurrent sessions to enhance security.
  • Cap session durations: Set a maximum time limit for sessions. After this period, users need to re-authenticate, reducing the risk of unauthorized access. For instance, configure sessions to expire after 8 hours of inactivity.
  • Revoke suspicious sessions: Watch for abnormal behavior and end any suspicious sessions. For example, terminate sessions with multiple failed login attempts or unusual login locations, prompting re-authentication with additional verification like MFA.

Ensure authentication comes from a trusted identity provider

Always check that the authentication tokens or credentials your app receives are from an identity provider you trust.In the case of SAML, make sure that:

  • All SAML assertions are always digitally signed by the IdP. When an IdP signs a SAML assertion, it uses a private key to create a digital signature. This signature enables the service provider to verify that the assertion has not been altered in transit and that it comes from the legitimate IdP.
  • As a service provider, you validate SAML messages signed only by a trusted IdP.
  • As a service provider, you check the signature of each assertion.
  • As a service provider, you validate the schema of SAML assertions using local, trusted copies.

In the case of OAuth, make sure the JWT is protected via JSON Web Signature (JWS) or JSON Web Encryption (JWE), and verify the issuer (iss) claim to ensure the JWT was issued by a trusted party.

Require Multi-Factor Authentication (MFA)

Adding MFA to your SSO integration introduces an additional layer of security. Even if someone gets hold of a user’s login credentials, they won’t be able to access the account without the second verification form.

Complement SSO with automated provisioning

SCIM (System for Cross-domain Identity Management) keeps user identity information in sync between systems. This means that whenever a user is created, updated, or deactivated in your customer’s identity provider, your app will automatically be updated. Keeping user data consistent and up-to-date without manual effort increases the security of your app and makes it easier for customers to use it. The problem is that each directory provider implements SCIM differently. Implementing SCIM in-house is challenging and can introduce security vulnerabilities into your app.

Replace email verification with domain verification

When a user logs in with an email from a verified domain, then you don’t need to send a verification email. Domain verification is crucial for establishing security and trust between service providers and organizations, ensuring that only authorized users can make changes to an organization's settings in the service provider.

Dynamically hide the password field

If you want to keep username/password authentication, consider disabling the password field for domains that have SSO enabled. This will improve the user experience, as the user can sign in with SSO immediately after filling in their email.

Enforce granular access control

Usually, authorization (what the user can access) is an afterthought and comes way later than authentication (who the user is), but in our opinion, it’s never too early to start thinking about it. At the bare minimum, you should enforce the principle of least privilege by ensuring that users have only the access necessary to perform their duties. Regularly review and adjust these permissions to adapt to changes in roles or responsibilities.

Consider real-time monitoring and logging

You should always be aware of user activities within your system. For example, you can use failed authentication events to identify problems with identity providers or attacks from malicious actors. You can take this one level up by using engines that monitor user activities and identify abusive or malicious behavior, like Radar. You should be able to detect (and block) bots, brute force attacks, and more.

Stay compliant

Compliance with industry regulations is more of a necessity than a best practice. There are specific regulations you will have to adhere to, especially if you are going after those enterprise deals.

Encrypt data in transit

When it comes to authentication, all data, such as tokens and credentials, should be encrypted using a strong algorithm while in transit. This will stop malicious actors from intercepting authentication data while a user is logging in.

Add social logins as part of your SSO strategy

It’s important to incorporate social logins as part of your SSO strategy. This allows users to log in with their existing social media accounts, which is great for websites serving enterprises and individual consumers. Enterprises can use corporate identity providers like Microsoft Entra or Okta, while consumers can use their social accounts.

SAML best practices

Manage certificate renewal

If you have worked with SAML, you know that certificate renewal can cause a lot of grief. Forgetting to renew one on time means an immediate loss of service, and you don’t want that. In order to keep your application’s SSO running smoothly with no downtime, you should make sure that you do the following:

  • Set up alerts based on certificate expiry dates: You should know beforehand when a certificate is about to expire so you have enough time to talk to customers and coordinate the renewal. Typically, a 90-day window should be sufficient.
  • Use dynamic metadata URLs: As the number of enterprise customers you have grows, it’s important to minimize having to request and upload a certificate for each expiry manually. Ask your customer to give you a metadata URL so you can dynamically fetch new certificates as they become available. This will ensure that if a customer sets up a new certificate in their identity provider, your application can fetch it using the metadata URL and be ready to switch over when it becomes activated.
  • Carefully orchestrate swapping out certificates: Some IdPs, like Okta, will only allow a single certificate to be active at any given time. This means that you must first get the new certificate from your customer, add it to your system, make sure that you are still processing existing requests using the old SAML certificate, and then start using the new one as soon as your customer activates it. This typically requires some coordination with your customer to ensure no downtime.

Implement deep linking

If you’re asking users to authenticate from an existing product page or they’re expecting to land somewhere in particular in your product, implement deep linking in your SAML flows. You can use SAML’s RelayState parameter for that. This is an HTTP parameter incorporated in both the SAML request and response. It holds a URL, and it’s set when SSO is initiated by the service provider so the identity provider knows where to send the response.

Use Just-In-Time user provisioning

JIT user provisioning automates the account creation process for users signing in to your app for the first time via SAML. If they exist in their organization’s IdP, you’ll just create their account automatically instead of asking them to sign up from scratch. Some of the benefits JIT offers are:

  • Reduced administrative work: JIT significantly cuts down on the administrative effort required to provision users – admins don’t have to manually create user accounts for every employee that needs access to your app; they get immediate access on their first login.
  • More paid seats: By allowing users to self-provision their access through JIT provisioning, you essentially empower entire organizations to onboard themselves onto your app. Because of this ease of access, your app can quickly increase the number of paid seats in the app from tens to hundreds or even thousands of users.
  • Less dormant or inactive accounts: By only creating accounts when needed, JIT provisioning reduces the risks associated with inactive or dormant user accounts – if users are able to log in to your app without SSO, then fewer unused accounts can mean fewer potential targets for hackers. Note that the accounts must be closed once they’re no longer used. Otherwise, the security risk is reintroduced.
  • Speed of access: Users don’t have to wait for admins to see and approve their access requests when they want to use an app. They can just sign in to the app and instantly get access.

Avoid common SAML security vulnerabilities

SAML is prone to security vulnerabilities, mainly because of the spec’s complexity and the lack of knowledge of the developers, who are often asked to implement it on a tight schedule. Here are some best practices to keep in mind:

  • Validate the SAML response schema first.
  • Check that you’re the intended recipient.
  • When it comes to XML, it’s best if you can completely disable external entities (i.e., XML entities with URIs that resolve to documents outside your control). If this is not possible, then external entities and external document type declarations must be disabled in a way that's specific to each parser.
  • Validate every signature (every assertion + the entire SAML response itself).
  • Validate SAML messages signed only by a trusted identity provider.
  • Validate the schema of SAML assertions using local, trusted copies.
  • Use the canonicalized XML.
  • Use HTTPS.
  • Only accept encryption schemes from an explicitly defined set of algorithms (e.g., RS256).
  • Use only well-known and recently updated open-source libraries for parsing XML.
  • Enforce Content Security Policy (CSP) headers on all SAML requests.
  • RelayState is an HTTP parameter incorporated in both the SAML request and response. It holds a URL, and it’s set when SSO is initiated by the service provider so the identity provider knows where to send the response (since SAML is async). However, an attacker can use this parameter to conduct open redirect attacks. To defend against such attacks, confirm the value of the RelayState is a trusted URL before redirection.
  • Set timestamps for the SAML assertions using the NotBefore and NotOnOrAfter attributes in the samlConditions tag.
  • Always encrypt SAML assertions that contain sensitive data.

For more details on SAML security vulnerabilities, see Common SAML security vulnerabilities and how to defend against them.

OAuth/OIDC best practices

Let’s see some best practices specific to OAuth 2.0 and OpenID Connect.

Use the proper OAuth flow

Whether your app executes on a browser, server, or TV affects which OAuth flow you should use:

Don’t use the Implicit grant since it’s insecure, and only consider using the Resource Owner grant if the client is 100% trusted.

Always validate tokens

Always validate the tokens before you use them. You need to ensure that the JSON Web Tokens (JWTs) can be trusted, haven’t been tampered with, and validate several token elements. Verifying and validating a JWT includes the following steps.

  • Parse the JWT to extract the header, payload, and signature.
  • Verify the signature using the secret key or public key.
  • Check the expiration time (exp) and the not-before time (nbf) claims to ensure the JWT is valid.
  • Verify the issuer (iss) claim to ensure the JWT was issued by a trusted party.
  • Verify the audience (aud) claim to ensure the JWT is intended for the correct recipient.

For more on this, see JWT validation: how-to and best libraries to use.

Use token encryption

It’s crucial always to use encrypted tokens. JWTs can be protected via JSON Web Signature (JWS) or JSON Web Encryption (JWE):

  • JWS uses a signature algorithm and is used to share data between parties when confidentiality is not required.
  • JWE uses a signature and encryption algorithm to guarantee confidentiality (i.e., only the receiver can decrypt data).

For more info, see Protecting JWTs: JWS, JWE, and JWK.

Handle tokens securely

Handle tokens and other sensitive information, like client credentials, in a secure manner. Encrypt tokens at rest for server-side apps that store tokens and ensure that your data store is not publicly accessible to the Internet. Use PKCE for client-side and native apps.

Use short-lived tokens

Use short-lived tokens to minimize resource exposure. An access token should last no more than a few minutes, and refresh tokens should last no more than a few days.

Handle token revocation

Use token revocation if possible. This allows the user or the authorization server to invalidate a token before it expires and is used in case it is compromised.

Use limited scope of access

Use a limited scope of access. Don’t request access to data unless it is essential for the core functionality of your app. Request only the specific scopes that are needed for a task. The user should always be able to easily understand why your application needs the access it is asking. Always select the smallest, most limited scopes possible. This is known as incremental authorization.If you need access to your customer’s email but might need access to their contacts list if the user chooses to enable some functionality that is by default disabled, then ask only for the email access when the user signs up. When and if they choose to enable that extra functionality, you can go ahead and ask for the additional scope so your app can access their contacts.

Handle consent for multiple scopes

Users may not grant all OAuth scopes you have requested when requesting multiple scopes at once. They might choose to share their email but not more than that. Your app should handle the denial of scopes by disabling relevant functionality.

Stay up-to-date

The OAuth 2.0 Security Best Current Practice is a work-in-progress that includes all the latest guidance on security best practices.

The most important SSO best practice

SSO might seem simple at first, but it’s not, and it gets more tricky the more identity providers and protocols you have to use. You can get many details wrong, and they can cost you and your users dearly.

For more info on how complex building authentication and authorization on your own can be, see our Build vs Buy series.

Don’t try to reinvent the wheel unless you absolutely have to. Many providers have already solved SSO and implemented authorization servers using best practices. Some are open source, others not.

Using a third-party service like WorkOS will save your engineering team a lot of time and effort to focus on what’s important: building your product.You can implement SSO using the WorkOS API directly if you want to build your own login box or use AuthKit.

  • Get started fast: With SDKs in every popular language, easy-to-follow documentation, and Slack-based support, you can implement SSO in minutes rather than weeks.
  • Support every protocol: With OAuth 2.0 integrations to popular providers like Google and Microsoft, compatibility with every major identity provider, and full support for custom SAML/OIDC connections, WorkOS can support any enterprise customer out of the box.
  • Avoid the back-and-forth: WorkOS’s Admin Portal takes the pain out of onboarding your customers’ IT teams and configuring your app to work with their identity provider.
  • Pricing that makes sense: Unlike competitors who price by monthly active users, WorkOS charges a flat rate for each company you onboard — whether they bring 10 or 10,000 SSO users to your app.

Sign up for WorkOS and start building today.

In this article

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.