When it comes to federated identity there are three major protocols used by companies: OAuth 2, OpenID Connect, and SAML. In this article we will examine their security weaknesses and how they relate to each other. Before diving deep into these protocols, let’s first clarify some concepts.
Federated identity is a secure way to link the electronic identities of a user across multiple identity management systems. In other words, an application can authenticate a user without needing to collect and store the credentials by using an identity management system that already knows the user’s identity. The main advantage of this approach is that it makes it easier to centralize authentication/authorization in enterprises, so different internal applications don’t need to manage users’ credentials themselves. Also, it is simple and convenient for users since they don’t need a unique username/password combination for every application.
Single Sign-On (SSO)
Single sign-on is a great way to simplify password management. It allows users to access multiple services/web applications with a single login. This means that once a user is logged into a service she automatically gains access to other services without having to re-submit credentials. For example, think of your Google account. Once you log in you can access Youtube, Google Ads, Google Analytics, or GMail without being asked for your username and password over and over again.
Authentication vs. Authorization
Authentication and Authorization are two terms and different concepts that people often confuse.
On a daily basis we interact with numerous computer devices and online services. Often we are required to confirm our identity to benefit from a personalized service or better security. We cannot simply provide a name, we also need to provide evidence to confirm our identity. This is authentication, the process that confirms a user’s identity based on one or more authentication factors. A factor can be something that user owns (digital signature, ID card, security token), something that user knows (password, PIN, secret answer) or what the user is (fingerprint, voice, retina scan).
Authorization has nothing to do with confirming a user’s identity. Its purpose is to determine which resources a user should be able to access and what they should be allowed to do with those resources. For example, once you log into a community board as an administrator, the authorization process makes sure that you can access specific resources and functions (such as admin control panel, edit/delete users’ posts functions), while an unprivileged user won’t be able to use those features. This process is useful in restricting free accounts from accessing premium features and preventing a user from modifying data that isn’t theirs.
To recap, authentication is verifying the identity of a user while authorization is deciding which resources a user should be able to access.
Now, let’s discuss the similarities and differences between the most used federated identity protocols: OAuth 2.0, OpenID Connect, and SAML 2.0.
OAuth 2 is an authorization framework that allows a user to grant external applications access to their data stored by another application (e.g., public profile, friends list, photos), without having to expose their credentials. To make things easier, let’s consider the following example:
You have just signed up on GMail, but you want to import your contact list from your old Yahoo inbox. During this process you will see the pop-up window from Figure 1 asking you to allow a third-party service to access your contacts, profiles, and others; that is OAuth 2. By clicking “Agree” the GMail app becomes authorized to access your Yahoo Mail data, but let’s find out how the protocol (i.e. OAuth 2) works.
Figure 1: Third-party app asking for access.
Oauth 2 defines four roles:
- Resource owner: the user that can grant access to the protected resource
- Client: the application that requests access to a protected resource
- Resource Server: the server that hosts a protected resource
- Authorization Server: the server that authorizes the client to access a protected resource
In the previous example you are the resource owner and the GMail application which tries to access your Yahoo Mail data is the client. Thus, api.mail.yahoo.com fulfills both the resource and authorization server roles.
To be able to delegate the authorization OAuth 2 can use four different process flows known as authorization grant types:
- Authorization Code Grant Type
- Implicit Grant Type
- Resource Owner Password Credentials Grant Type
- Client Credentials Grant Type
In this article we will discuss the first two grant types as the others are rarely used. To gain access to the protected resource OAuth 2 follows a three-step process described in Figure 2.
Figure 2: Basic OAuth 2 workflow (Source: Auth0).
- First, the Client (application) spawns a browser window similar to the one from Figure 1 asking for Resource Owner’s authorization to proceed further.
- Once the Resource Owner approves the access the Client receives a verification code -a simple randomly generated string.
- The Client requests an Access Token from Authorization Server by providing the verification code acquired in the previous step.
- If the verification code is correct the Authorization Server generates an Access Token and sends it to the Client.
- The Client makes an HTTP request to access the protected resource located on the Resource Server including the Access Token in the request.
- If the Access Token is valid the Client is allowed to access the protected resource.
OAuth 2.0 vulnerabilities
With a search on HackerOne’s platform you can see there are many vulnerabilities related to this technology (see Figure 3). So, what is the problem? Is OAuth 2 an insecure protocol? The answer is no.
Even though some things could be improved, OAuth 2 is secure. It is important to understand that OAuth 2 was built to eliminate the need for a specific insecure anti-pattern (i.e., exposing username and password to third parties during authorization granting process). So, the problem is not the protocol itself, but rather how developers implement it. All the potential vulnerabilities that may arise due to faulty implementation of the OAuth 2 have been well-documented in RFC 6819, just a few months after the second major version of the protocol was released.
Figure 3: Vulnerabilities disclosed on HackerOne affecting OAuth instances
We won’t discuss all the implementation vulnerabilities related to OAuth 2 but focus on the most prevalent. So, let’s start with the first one: Account Takeover via Open Redirect.
Account Takeover via Open Redirect
The account takeover vulnerability that can affect OAuth 2 occurs due to improper sanitization of the redirect_uri parameter, allowing an attacker to hijack a victim’s verification code/access token and take over their account.
A typical request URL that asks for a validation code (step 2 from Figure 2) has the following structure:
If the web application doesn’t perform strict checks for redirect_uri parameter, an attacker may be able to change the value to his own website. E.g.:
If a user of webapp.com tries to log in using the above link his browser will send the verification code to the attacker’s website. The attacker can make a manual request to the original redirect_uri providing the victim’s verification code:
https://dashboard.webapp.com/callback?code=victim's verification code
The web application will respond with an access token that can be used to access protected resources on behalf of the victim.
This vulnerability is easy to fix by implementing a allowlist on the redirect_uri parameter. However, make sure your filter matches exact values, otherwise it may be possible to bypass it using some tricks such as
Account takeover via CSRF
Another way to gain access to a victim’s account is by using a CSRF attack. If you are not familiar with this type of attack yet you can check out HackEDU’s hands-on CSRF lesson.
The process is straightforward: first, the attacker initiates the OAuth workflow on example.com by choosing to log in with his social media account (e.g., Facebook). However, he will not complete the process and instead stop at step 4 (see Figure 2), just after the authorization code has been generated.
The attacker creates a CSRF exploit that makes a request to:
https://example.com//auth/facebook/callback?code=<attacker’s authorization code>
If the victim is logged in to example.com while visiting attacker’s website, the attacker’s social media account will be linked to the victim’s account.
CSRF attacks on OAuth endpoints can be prevented by appending the state parameter to the requests. This parameter is optional and acts similar to the traditional CSRF tokens.
If you are interested in learning more about OAuth 2.0 you can check out these great resources:
- The OAuth 2.0 Authorization Framework
- OAuth 2.0 Simplified
- OAuth 2.0 Threat Model and Security Considerations
Next we will discuss the differences and similarities between OAuth 2 and OpenID Connect.
OpenID Connect (OIDC) is an authentication protocol widely supported and used by Google, Paypal, Verizon, Microsoft, Salesforce, Amazon, and many others. If you ever used the “Log in with Paypal” feature when shopping online, that was OIDC - a web-based SSO service that allows a user to login to a website/application by authenticating with an identity provider.
Despite its name, OpenID Connect is not based on the first version of the protocol (OpenID), but instead on OAuth 2.0 specifications. More specifically, OpenID Connect extends OAuth 2 capabilities by implementing user authentication through cryptographically secured token, sharing basic profile information about the user, as well as some other important features and additional security improvements.
As you can see in Figure 4, the OIDC and OAuth 2 workflows are similar. The main difference is that OIDC uses id_token for an authentication purposes. This parameter which contains information about the authenticated user is sent back to the Client in a JSON Web Token (JWT) format during the last step of the workflow, along with the access_token. JWT is a simple yet efficient way to transfer information between two parties securely. Information in the JWT is digitally-signed, which means every trusted party that can handle a JWT can tell whether or not the token has been changed in any way. If you are not familiar with this technology you can check out HackEDU’s hands-on lesson about JWT tokens and potential issues.
Figure 4: OpenID Connect Authentication workflow (Source: Onelogin Developers)
Since OpenID Connect is based on OAuth 2.0 some of the potential issues described in RFC 6819 - OAuth 2.0 Threat Model and Security Considerations are applicable here too. Also, OIDC Security Considerations Section specifies additional attack vectors and mitigations that should be considered. OIDC does contains improvements that solve a number of security issues related to OAuth 2.0.
OpenID Connect vs. OAuth 2.0
The most important difference between those two protocols is that OpenID is an authentication protocol, while OAuth 2.0 is an authorization protocol. The other differences and similarities are summarized in the following table:
OAuth 2.0OpenID ConnectPurposeAuthorizationAuthorization, authentication and API access managementUse-caseUseful to protect APIsNew web or mobile applications, SSO for consumer appsLimitationsDoes not include authenticationFormatJSONJSONSet-up difficultyEasy to implement and useEasy to implement and useScalabilityEasy to scaleEasy to scale
Security Assertion Markup Language (SAML) is an XML-based open-standard which simplifies the authentication and authorization process between two parties: an Identity Provider and Service Provider. In other words, SAML allows you to use a single pair of credentials to log into multiple web applications. In contrast to OpenID Connect, this protocol is often used in enterprise networks to give users access to specific 3rd party services.
SAML works by securely exchanging authentication and authorization data in XML format between the user, Service Provider, and Identity Provider.
The Identity Provider is the system which verifies the user’s identity. It performs the authentication process and sends the user’s information as well as the access rights for the service to the Service Provider. A commonly used identity provider is Microsoft Active Directory, Okta, or OneLogin.
The Service Provider is the system which receives and accepts information from the Identity Provider (e.g., Salesforce, Office365, Slack).
Once a user logs into a SAML instance the Service Provider request authorization to access the user’s data from the Identity Provider. The Identity Provider validates the user’s credentials and tries to authenticate them. If the credentials are valid the Service Provider will receive the authorization and the user will be allowed to use the application.
All these transactions are performed through SAML assertions - XML documents that contain the authorization data. There are three types of assertions: authentication, attribute, and authorization assertion.
In Figure 5, you can see the SAML’s workflow:
Figure 5: SAML workflow (source: https://www.mutuallyhuman.com/blog/choosing-an-sso-strategy-saml-vs-oauth2/)
Let’s suppose that Steve wants to log into an internal Salesforce instance. Since the application uses SAML for authentication/authorization it starts by generating a SAML request.
The browser redirects Steve to the Identity Provider (OneLogin for example) which also parses the SAML request and asks Steve for his credentials. If the credentials are valid then the Identity Provider creates the authentication response that includes Steve’s identity information (email/username), signs it using an X.509 certificate, and sends it to the Service Provider (Salesforce app).
During the last step the Service Provider (Salesforce) verifies the SAML assertions and extracts the relevant information about Steve. Now Steve can browse the application as a logged-in user.
A successful attack on a SAML instance can be a critical risk. In some cases an attacker can take over a victim’s account or even get unauthorized access to the entire system. There are many potential vulnerabilities that you should check for, but you can speed up the process using different tools such as SAML Raider to quickly detect and test SAML misconfigurations.
The vulnerabilities are due to improper implementation and not from the protocol itself. We’ll briefly discuss two of the most common attacks on SAML: XML Signature Wrapping and a more recently discovered Authentication Bypass.
XML Signature Wrapping
Most of SAML security issues are caused by the incorrect implementation of the XML signature/encryption. XML Signature Wrapping is an attack in which the structure of signed elements is modified so that the application logic evaluates the newly created elements. This allows an attacker to send arbitrary requests as a legitimate user.
Figure 6: Encrypted SOAP message protected by an XML Signature Source: How to break XML encryption
Figure 7: XML Signature Wrapping attack applied on an encrypted and signed message shown in Figure 6.
As you can see in Figure 7, the original Body element has been moved to the Header section, and a newly created Body was introduced. A vulnerable application finds the Body element in the Header section and verifies the XML Signature. If the signature is valid, it decrypts the EncryptedData element where the attacker introduced his malicious content.
This attack is possible because the position of the signed elements were not fixed. This means that the signature is valid regardless of the location of the element allowing an attacker to change the structure of the base document.
SAML Authentication Bypass
On February 27, 2018, Duo Security announced they found an authentication bypass vulnerability affecting several widely-used SAML libraries. The issue allows an authenticated attacker to login to other users’ accounts without knowing their password.
Below are the steps required for a successful attack:
- The attacker logs into his account (email@example.com) and tries to access a resource.
- The Identity Provider generates a SAML assertion containing the user identifier (email address) and sends it back to the Service Provider.
- Now the attacker updates his email address in the SAML assertion, and adds an XML comment right before .evil.com: firstname.lastname@example.org.
- Due to an XML parsing issue the SAML Processing Library ignores the comment and everything after it. Thus, the Service Provider processes email@example.com as the real email address of the attacker instead of firstname.lastname@example.org.
- As a result, the attacker is allowed to access the protected resource on behalf of email@example.com.
If you run an Identity Provider or Service Provider the best way to avoid this vulnerability is to make sure that you are not using a vulnerable SAML processing library (you can find a list of affected libraries here). Additionally, you can enable two-factor authentication to prevent an attacker from accessing the victim’s account.
SAML vs. OpenID Connect vs. OAuth 2
SAML and OpenID Connect support both authentication and authorization while OAuth 2 was created to delegate the authorization process.
SAML is definitely the hardest to implement but offers great flexibility. Since SAML only handles the information exchange between the Identity Provider and the Service Provider it allows the developer to choose how the users authenticate. The following table summarizes some of the differences and similarities between these three protocols.
|OAuth 2.0||OpenID Connect||SAML|
|Purpose||Authorization||Authorization, authentication and API access management||Authorization, authentication|
|Use-case||Useful to protect APIs||New web or mobile applications, SSO for consumer apps||Existing federations, enterprise SSO|
|Limitations||Does not include authentication||Not designed for designed for mobile or native applications.|
|Set-up difficulty||Easy to implement and use||Easy to implement and use||Hard to implement|
|Scalability||Easy to scale||Easy to scale||Depends on implementation|
|Can invalidate an access tokens?||Yes||Yes||No|
|Transport||HTTP||HTTP (GET & POST)||HTTP Redirect binding, HTTP POST binding, SAML SOAP binding, HTTP Artifact binding, SAML URI binding|