Web API History Series • Post 89 of 240
Chapter 89 (1995–1998): Before OAuth—How Browser Scripting, CGI, and Forms Shaped Modern API Authorization
A chronological, SEO-focused guide to OAuth 2.0 and modern API authorization in web API history and its role in the long evolution of web APIs.
Chapter 89 (1995–1998): Before OAuth—How Browser Scripting, CGI, and Forms Shaped Modern API Authorization
Post 89 of 240 in a chronological history of web APIs.
When people talk about modern API authorization, OAuth 2.0 is usually the headline act: bearer tokens, scopes, consent screens, and delegated access that lets one service call another without handing over a password. But OAuth 2.0 arrived much later. If you want to understand why OAuth exists—and why it looks the way it does—it helps to rewind to the mid-to-late 1990s, when many “APIs” were really just web pages plus a script on the server.
In the 1995–1998 era, the building blocks of web integration were HTML forms, CGI programs, early server-side templates, and the new idea of browser scripting (notably JavaScript) to glue interactions together. This chapter isn’t about OAuth itself (it wasn’t part of that time). It’s about the authorization and identity patterns that developers used back then—and how those patterns created the exact problems OAuth 2.0 later aimed to solve.
What Counted as a “Web API” in 1995–1998?
Today, a web API typically means a stable HTTP endpoint returning JSON, with a documented contract and structured authentication. In the 1995–1998 window, integration often looked like this:
- HTML forms as an interface contract: A browser would POST or GET name/value pairs. The “API surface” was the set of form fields.
- CGI scripts as endpoints: A URL mapped to an executable (often in Perl or C). The script read parameters, hit a database, and returned HTML.
- Early dynamic web techniques: Server-side includes and early templating let sites assemble pages from data, blurring “web page” and “service.”
- Browser scripting: Early JavaScript validated fields, manipulated forms, and sometimes helped pass state from one page to another.
From a modern perspective, these were proto-APIs: HTTP-based entry points that accepted input and produced output, but often without the explicit boundary between “front end” and “service” that we take for granted now.
Authorization, Then: Passwords, Sessions, and Trust by Convention
In this era, “authorization” mostly meant “is the user logged in?” and “does this request have the right cookie?” The typical approaches were simple, pragmatic, and tightly bound to the browser:
1) HTTP Basic Authentication
Basic auth (username and password sent with each request) was one of the most straightforward options available. It worked with many servers and didn’t require much custom code—useful when a “web API” was simply a protected directory plus a CGI script.
But Basic auth had serious drawbacks for anything that resembled delegated access. If a third-party tool needed access, the only widely used option was often “give it the password,” which is exactly the anti-pattern OAuth later replaced. For technical background on Basic auth, the IETF’s documentation is still a useful reference: RFC 2617 (HTTP Authentication: Basic and Digest Access Authentication).
2) Cookies and Server-Side Sessions
Cookies enabled the classic “session ID” model: authenticate once, then the browser automatically sends the cookie on subsequent requests. This was excellent for interactive web apps and quickly became a standard way to track user identity across multiple page loads.
Yet cookies were implicitly browser-centric. They solved “keep the user logged in,” not “let another application call an API on the user’s behalf.” There was no widely adopted way to express fine-grained permissions (what OAuth later calls scopes) or to limit a third party’s access without sharing full login credentials.
3) Hidden Fields and URL Parameters
Because forms dominated integration, many applications stuffed state into hidden inputs or query strings: user IDs, action tokens, workflow steps, even authorization hints. It worked—until it didn’t. URLs could leak through browser history, referrer headers, server logs, or copy/paste. Hidden fields reduced visibility but not risk; the browser still sent them in the clear to the server, and users could tamper with them.
These patterns shaped the security mindset of the time: a mix of server-side validation and informal assumptions about how browsers behave. As web APIs grew beyond the browser, those assumptions began to crack.
Browser Scripting Appears: A New Power, A New Surface Area
Mid-1990s browser scripting introduced a subtle shift in how developers thought about “clients.” Before scripting, the browser was mostly a renderer that navigated from document to document. With JavaScript, the browser became an active participant: it could validate inputs, choose which endpoint to call (by selecting a form action or building a URL), and dynamically submit requests.
That mattered for authorization because it made it easier to build multi-step flows—precursors to the later “authorization dance.” Developers could:
- Detect whether a user was “logged in” (often indirectly via page content) and redirect them through a login form.
- Carry transient state through form submissions and redirects.
- Create early “single sign-on-ish” experiences across pages by automating navigation.
But scripting also widened the attack surface. If authorization data lived in the page (hidden fields, URL parameters, embedded identifiers), scripting could manipulate it. The web started to need clearer boundaries: what the client may request, what the server must verify, and what a third party should never see.
CGI as the Proto-API Layer: Useful, but Not a Delegation Story
CGI programs were often the “API server” before anyone used that phrase. A script could accept parameters and return results. If you squint, a CGI endpoint that returns HTML is still an API endpoint—it’s just an API optimized for humans, not machines.
In 1995–1998, the common model was:
- User authenticates in the browser (via Basic auth or a session cookie).
- Browser submits a form to a CGI script.
- CGI script checks identity (cookie/session) and performs an action.
This was a strong pattern for first-party experiences. The same company controlled the UI, the endpoints, and the credential store. OAuth 2.0, by contrast, is fundamentally about multi-party integration: a resource owner (user), a client (app), an authorization server, and a resource server. That four-role mental model is what the 1990s web lacked.
The Core Problem the 1990s Couldn’t Solve Cleanly: Delegated Authorization
To see the gap, imagine a late-1990s scenario in modern terms: a user wants a third-party app to “access my data, but not my password, and only for this specific purpose.” In 1995–1998, that request ran into multiple blockers:
- No standardized consent model: There wasn’t a common UX pattern or protocol for “approve this other app.”
- No token vocabulary: Sessions existed, but a portable, time-limited bearer token with explicit scope was not a mainstream web concept.
- Weak separation of concerns: Authentication and authorization were often intertwined. If you proved who you were, you got broad access.
- UI and API were fused: Many services exposed actions through HTML meant for browsers. Programmatic clients had to screen-scrape or simulate form submissions, dragging user credentials along with them.
From a historical angle, this is the “missing chapter” that makes OAuth 2.0 feel inevitable. The web learned how to identify users (sessions), but it hadn’t yet learned how to safely let other software act for those users with limited authority.
How These Early Patterns Echo in OAuth 2.0
OAuth 2.0 is often described in terms of tokens and flows, but it also reflects lessons learned from those earlier mechanics:
Redirects and form posts → Authorization flows
The 1990s web was already good at “send the user to another page, then come back.” Login pages, payment gateways, and multi-step checkout processes all relied on redirects and form submissions. OAuth 2.0 formalized a secure version of that pattern: send the user to an authorization server, collect consent, then return the user (and the client) with verifiable proof.
Sessions → Tokens with boundaries
Session cookies demonstrated the convenience of not asking for a password on every request. OAuth borrowed the convenience, but made it portable and more granular: a token can be limited by time, audience, and scope in ways that a generic “logged-in session” often was not.
Ad-hoc parameters → Standardized claims and scopes
Hidden fields and query parameters were the duct tape of early integration. OAuth replaces duct tape with standards: consistent parameter names, defined error handling, and a shared vocabulary for permissions (scopes). It’s the difference between “we both agreed this field means admin=true” and “this token is only valid for read-only access to a specific resource.”
If you build or test modern API authorization systems today, it can be useful to keep that historical context in mind. Many security bugs still look like 1990s bugs—sensitive state in URLs, over-broad sessions, or trusting the client too much—only now they happen at API scale. For more practical explorations of automation and security-minded development, you can also browse AutomatedHacks.com.
Where Chapter 89 Fits in Web API History
This 1995–1998 period is a hinge in the history of web APIs. It’s when the web started to behave less like a library of documents and more like a programmable application platform—yet it still lacked the explicit API boundaries and standardized authorization mechanisms we rely on now.
By the end of the decade (and especially as web services matured in the following years), the demand for clean programmatic interfaces grew. Once third-party integrations became normal, “just share a password” stopped being acceptable. OAuth 2.0 is best understood as the long-term response to this early era’s constraints: forms, CGI, cookies, and scripting showed what was possible, and their shortcomings showed what needed to be invented.
FAQ: OAuth 2.0 and the 1995–1998 Web
- Was OAuth 2.0 used in 1995–1998?
- No. OAuth 2.0 came much later. This chapter explains the earlier web patterns that made a standard like OAuth necessary.
- What was the most common “API authentication” pattern in the late 1990s?
- For browser-based apps, session cookies were common. For protected resources and simple integrations, HTTP Basic authentication was widely used.
- Why didn’t hidden fields and URL parameters work as a safe authorization system?
- They were easy to leak (logs, history, referrers) and easy to tamper with. They also lacked a standardized way to express limited permissions.
- What’s the key idea OAuth added compared to 1990s login systems?
- Delegation: an app can receive limited access to a user’s resources without learning the user’s password, typically via tokens with defined scope and lifetime.
