What you'll learn
Quick Answer
OAuth lets an application get limited access to your account on another service without seeing your credentials. You log in with the provider, the provider hands the app a short code, and the app exchanges that code for an access token.
The problem it solves
Imagine an app that needs to read your Google Calendar. The naive approach is to ask for your Google password and log in as you.
That is catastrophic. The app now has full access to your email, your files and your account recovery. If it is breached, so are you. If you want to revoke access, your only option is changing your password, which breaks every other app you did the same thing with.
OAuth fixes it with a redirect. You authenticate with Google, on Google's own page, and Google hands the app a token limited to exactly what you approved. The app never sees your password, the token can be scoped to calendar-read-only, and you can revoke it from your Google account settings without affecting anything else.
The authorisation code flow
This is the flow to know — the others exist but this is the one used by web applications.
- Redirect. You click "Sign in with Google". The app sends you to Google with its client ID, the scopes it wants, a redirect URI and a random
statevalue. - Authenticate and consent. You log in on Google's page and see exactly what is being requested. The app is not involved and cannot observe this.
- Code returned. Google redirects you back to the app's redirect URI with a short-lived authorisation code in the URL.
- Exchange, server to server. The app's backend sends that code plus its client secret directly to Google and receives an access token.
- Use the token. The app calls Google's API with the token in an
Authorization: Bearerheader.
Step 4 is the one worth understanding. Why not give the token directly at step 3? Because that redirect goes through the browser, where the token would be visible in the URL, in history and in server logs. The code is useless without the client secret, which only the backend holds — so intercepting the redirect gains an attacker nothing.
Access tokens, refresh tokens and scopes
The access token is what you send with API calls. It is deliberately short-lived — often an hour — so a leaked token has limited value.
The refresh token is long-lived and used only to obtain new access tokens without the user logging in again. It is far more sensitive, must never reach the browser, and is what you revoke to cut off access.
Scopes define what the token can do. Requesting calendar.readonly rather than full account access is the principle of least privilege in practice, and users increasingly notice over-broad requests on the consent screen.
The state parameter from step 1 is not decoration — it is CSRF protection. The app generates a random value, stores it in the session, and verifies it matches on return. Without it, an attacker can trigger a callback that links their account to your session. Skipping state is a real and common vulnerability.
OAuth is not authentication — OpenID Connect is
A distinction that catches people, including in interviews.
OAuth is about authorisation — granting an application permission to do something. It says nothing about who you are. An access token proves the app may call an API; it does not reliably prove your identity.
OpenID Connect is a thin layer on top of OAuth that adds identity. Alongside the access token you receive an ID token — a signed JWT containing who the user is, who issued it, which application it was issued for, and when it expires.
So "Sign in with Google" is really OpenID Connect. When implementing login, you must verify the ID token's signature, issuer, audience and expiry. Accepting an unverified token, or one issued for a different application, is a serious flaw — and it is easy to get wrong by reading the token without checking it.
See API authentication explained for what to do with the session afterwards.
Practical guidance
- Use a library. Do not implement OAuth by hand. Every major language has a well-maintained client, and the failure modes here are security failures rather than bugs.
- Keep the client secret on the server. It is not a secret if it ships in JavaScript or a mobile app binary.
- Public clients use PKCE. Single-page apps and mobile apps cannot hold a secret, so they use Proof Key for Code Exchange, which substitutes a per-request generated value. It is now recommended for all clients.
- Register redirect URIs exactly. Loose matching is how tokens get redirected to attacker-controlled URLs.
- Request minimal scopes. Both for security and because a consent screen asking for everything reduces sign-ups.
For a student project, using a provider's OAuth for login is genuinely a good decision — you avoid storing passwords entirely, which removes a whole category of risk you would otherwise have to handle correctly.
