OAuth 2.0 Authentication and Attack Surface
0x00 Prerequisites: I have recently been testing issues related to my company’s OAuth authentication and needed to familiarize myself with it again, so I decided to write about it. 0x01 OAuth 2.0 Concepts: OAuth is an open web standard for authorization and is currently the most common and widely used authorization protocol. Where is OAuth 2.0 used? It is actually very common…
Read in Chinese→0x00 Prerequisites
I have recently been testing issues related to my company’s OAuth authentication and needed to familiarize myself with it again, so I decided to write about it.
0x01 OAuth 2.0 Concepts
OAuth is an open web standard for authorization and is currently the most common and widely used authorization protocol.
Where is OAuth 2.0 used? It is actually very common.
Our quick-login features use it. Here is an example:

So why do we use it?
The reasoning is actually very simple. First, it is undoubtedly convenient for our website to provide this type of quick login. However, a third-party website and our website cannot completely trust each other, and neither can hand user information over to the other for storage. Therefore, OAuth generally allows users to grant this access without exposing their login credentials to the requesting application. This means that users can choose which data they want to share without giving their account credentials to a third party.
0x02 Process Overview
For ease of understanding, we will demonstrate the process directly with an example. First, we need to distinguish the different roles. We can divide them into four parts:
resource owner: the user
resource server: the website we want to log in to quickly, zeo.cool
User Agent: the browser.
authorization server: a third-party authorization server, such as Google’s authorization server. This is a server used specifically by the service provider to handle authentication and authorization. After successful authentication, it issues an access token to the client, authenticates the resource owner, and obtains authorization.
client_id: this represents the website backend—our zeo.cool website backend.
In practice, there are four implementation methods:
- Authorization Code
- Implicit
- Password
- Client Credentials
0x03 Prerequisites
A third-party application, zeo.cool, first registers with Google’s authentication center.
It provides a callback URL: https://zeo.cool/oauth_calback
It then receives:
ClientID = 888888: an identifier for my website, zeo.cool
ClientsecretID = 6666666: this is similar to a private key. It must be stored securely and never disclosed.
0x04 Token Mode
The authorization code flow is the most commonly used mode in OAuth 2.0.
The authorization code flow is the most comprehensive and rigorous authorization mode. Its defining characteristic is that the client’s backend server interacts with the service provider’s authentication server.

Note: The lines illustrating steps (A), (B), and (C) are split into two parts where they pass through the user agent. They are divided into two parts as they pass through the user agent.
(A) The user accesses the client, which directs the user to the authentication server.
The URI through which the client requests authentication contains the following parameters:
response_type: indicates the authorization type and is required. Its value is fixed as “code” here.
client_id: indicates the client ID and is required.
redirect_uri: indicates the redirect URI and is optional.
scope: indicates the requested permission scope and is optional.
state: may be set to any random string and is optional.
https://www.google.com/v1/oauth/authorize?response_type=code&client_id=888888&redirect_uri=CALLBACK_URL&scope=read&state=dslakf54jlk5li54j
(B) The user chooses whether to authorize the client.
(C) If the user grants authorization, Google’s authentication server directs the user to the redirection URI specified by the client while appending the authorization code. After the user clicks to authorize, Google directs the user to the redirect URL specified in step A, carrying the authorization code and state.
code: indicates the authorization code and is required. The code should have a very short validity period, usually 10 minutes, and the client can use it only once; otherwise, the authorization server will reject it. The code has a one-to-one relationship with the client ID and redirect URI.
state: may be set to any random string and is optional.
https://zeo.cool/oauth_calback?code=SplxlOBeZQQYbYS6WxSbIA&state=dslakf54jlk5li54j
(D) After the zeo.cool backend client receives the code, its backend server sends the code and redirection URI to the authentication server. After zeo.cool receives the request from step (C), it uses the authorization code to send the following request to Google’s authentication server for a token.
grant_type: indicates the authorization mode and is required. Its value is fixed as “authorization_code” here.
code: indicates the authorization code obtained in the previous step and is required.
redirect_uri: indicates the redirect URI and is required. It must be identical to the value of this parameter in step A.
client_id: indicates the client ID and is required.
(Server-side backend operation)
https://www.Google.com/v1/oauth/token?client_id=888888&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL
(E) Google’s authentication server validates the code and redirection URI. After confirming that they are correct, it responds to the client with an access token and refresh token. This is the response to the data from step (D).
access_token: indicates the access token.
token_type: indicates the token type; this value is case-insensitive.
expires_in: indicates the expiration time.
refresh_token: indicates the refresh token.
scope: indicates the permission scope.
{
"access_token":"sdjlkh13khekj2hjkhd23kjd",
"token_type":"xxx",
"expires_in":3600,
"refresh_token":"zxfdcsa34323dxccc3",
"example_parameter":"xxxxx"
}
Finally, my website, zeo.cool, can take the access_token to Google and exchange it for the corresponding information.
Why issue an authorization code first and then exchange it for a token?
This is because browser redirection—usually an HTTP 302 redirect—is visible to the user. In other words, the authorization code may be exposed to the user and to other programs on the user’s machine. However, because the user does not have the Clientsecret and cannot exchange an authorization code alone for a token, this prevents the token from being leaked during redirect transmission.
0x05 Token Mode—Attack Surface
(1) Security issues in the authorization code flow often involve CSRF attacks:
In step (A), there is an optional parameter named state. The state value is generated by the server as a random string and stored in the session.
The state is then included in the request from step (A). Google returns the user to our website with a URL containing the authorization code and state.
At this point, the server backend needs to compare the state values to verify that they match, thereby preventing CSRF attacks.
If state is absent, the following attack becomes possible.
-
The hacker first obtains their own code.
-
The hacker creates a CSRF page that performs step C, causing the victim to use their own cookie to complete the binding.
-
Ultimately, the victim’s cookie is bound to the hacker’s account.
(2) Callback URL Validation Issues
If there is a problem with callback validation, such as:
By using techniques to bypass the regular expression, the redirect can be sent to hacker.com, carrying your code along with it.
This code can then be used for subsequent attacks.
https://www.google.com/v1/oauth/authorize?response_type=code&client_id=888888&[email protected]?call_back&scope=read&state=dslakf54jlk5li54j
0x06 Implicit Mode (Implicit Grant Mode)
The implicit grant type does not use the third-party application’s server.
Instead, it requests a token directly from the authentication server in the browser, skipping the “authorization code” step—hence the name.
All steps are completed in the browser, the token is visible to the visitor, and the client does not need to authenticate.

(A) The client directs the user to the authentication server.
In step A, the HTTP request sent by the client contains the following parameters:
response_type: indicates the authorization type. Its value is fixed as “token” here and is required.
client_id: indicates the client ID and is required.
redirect_uri: indicates the redirect URI and is optional.
scope: indicates the permission scope and is optional.
state: indicates the client’s current state. It may be set to any value, and the authentication server returns this value unchanged.
https://www.Google.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx
(B) The user decides whether to authorize the client.
(C) Assuming the user grants authorization, the authentication server directs the user to the “redirect URI” specified by the client and includes the access token in the URI fragment.
In step C, the URI returned by the authentication server to the client contains the following parameters:
access_token: indicates the access token and is required.
token_type: indicates the token type. This value is case-insensitive and is required.
expires_in: indicates the expiration time in seconds. If this parameter is omitted, the expiration time must be set by another method.
scope: indicates the permission scope. This may be omitted if it matches the scope requested by the client.
state: if the client’s request contains this parameter, the authentication server’s response must contain the exact same value.
https://www.example.com/callback#access_token =ACCESS_TOKEN&state=xyz&token_type=example&expires_in=3600&state=xxx
Use Cases
-
Suitable for any application without server-side support.
-
Examples include mobile or desktop client programs and browser extensions.
-
Applications implemented using client-side scripting languages such as JavaScript.
0x07 Implicit Mode Attack Surface
Account hijacking under the implicit grant mode
(1) In a real-world scenario, a CSRF attack can be performed when the state parameter is absent.
(2) The redirect_uri can be forged when the provider does not properly validate it.
What we need to do is find an XSS vulnerability on a trusted website, then redirect to obtain and hijack the access_token. Once the access_token has been obtained, the full attack can be completed.
0x08 Password Mode
In the Resource Owner Password Credentials Grant, the user provides their username and password to the client. The client uses this information to request authorization from the service provider.
This direct use of account credentials is extremely rare because it goes against the original design.

(A) The user provides a username and password to the client.
(B) The client sends the username and password to the authentication server and requests a token.
In step B, the HTTP request sent by the client contains the following parameters:
grant_type: indicates the authorization type. Its value is fixed as “password” here and is required.
username: indicates the username and is required.
password: indicates the user’s password and is required.
scope: indicates the permission scope and is optional.
https://www.google.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID
(C) After verifying the information, the authentication server provides an access token to the client.
{
"access_token":"df908f890sdf09asd890",
"token_type":"example",
"expires_in":3600,
"refresh_token":"saf43r243fd34f4fg32g",
"example_parameter":"example_value"
}
0x09 Client Credentials Mode
The Client Credentials Grant means that the client authenticates with the service provider on its own behalf rather than on behalf of a user. Strictly speaking, the client credentials mode does not belong to the problem that the OAuth framework is intended to solve. It will not be explained in detail here; only the process is covered.
This is mostly used in microservice environments, where backend services perform authorization tasks themselves.

The process for this mode is as follows:
(A) The client authenticates with the authentication server and requests an access token.
granttype: indicates the authorization type. Its value is fixed as “client_credentials” here and is required.
scope: indicates the permission scope and is optional.
https://www.example.com/token?grant_type=client_credentials
(B) After verifying the information, the authentication server provides an access token to the client.
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"example_parameter":"example_value"
}
0x10 Summary
The main attack surfaces are CSRF binding and hijacking vulnerabilities, as well as unvalidated callback URLs—bypassing validation directly or in combination with URL redirect bypasses and similar techniques.