578 lines
21 KiB
HTML
578 lines
21 KiB
HTML
|
<HTML
|
||
|
><HEAD
|
||
|
><TITLE
|
||
|
>Authenticating on the Web</TITLE
|
||
|
><META
|
||
|
NAME="GENERATOR"
|
||
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
||
|
REL="HOME"
|
||
|
TITLE="Secure Programming for Linux and Unix HOWTO"
|
||
|
HREF="index.html"><LINK
|
||
|
REL="UP"
|
||
|
TITLE="Special Topics"
|
||
|
HREF="special.html"><LINK
|
||
|
REL="PREVIOUS"
|
||
|
TITLE="Passwords"
|
||
|
HREF="passwords.html"><LINK
|
||
|
REL="NEXT"
|
||
|
TITLE="Random Numbers"
|
||
|
HREF="random-numbers.html"></HEAD
|
||
|
><BODY
|
||
|
CLASS="SECT1"
|
||
|
BGCOLOR="#FFFFFF"
|
||
|
TEXT="#000000"
|
||
|
LINK="#0000FF"
|
||
|
VLINK="#840084"
|
||
|
ALINK="#0000FF"
|
||
|
><DIV
|
||
|
CLASS="NAVHEADER"
|
||
|
><TABLE
|
||
|
SUMMARY="Header navigation table"
|
||
|
WIDTH="100%"
|
||
|
BORDER="0"
|
||
|
CELLPADDING="0"
|
||
|
CELLSPACING="0"
|
||
|
><TR
|
||
|
><TH
|
||
|
COLSPAN="3"
|
||
|
ALIGN="center"
|
||
|
>Secure Programming for Linux and Unix HOWTO</TH
|
||
|
></TR
|
||
|
><TR
|
||
|
><TD
|
||
|
WIDTH="10%"
|
||
|
ALIGN="left"
|
||
|
VALIGN="bottom"
|
||
|
><A
|
||
|
HREF="passwords.html"
|
||
|
ACCESSKEY="P"
|
||
|
>Prev</A
|
||
|
></TD
|
||
|
><TD
|
||
|
WIDTH="80%"
|
||
|
ALIGN="center"
|
||
|
VALIGN="bottom"
|
||
|
>Chapter 11. Special Topics</TD
|
||
|
><TD
|
||
|
WIDTH="10%"
|
||
|
ALIGN="right"
|
||
|
VALIGN="bottom"
|
||
|
><A
|
||
|
HREF="random-numbers.html"
|
||
|
ACCESSKEY="N"
|
||
|
>Next</A
|
||
|
></TD
|
||
|
></TR
|
||
|
></TABLE
|
||
|
><HR
|
||
|
ALIGN="LEFT"
|
||
|
WIDTH="100%"></DIV
|
||
|
><DIV
|
||
|
CLASS="SECT1"
|
||
|
><H1
|
||
|
CLASS="SECT1"
|
||
|
><A
|
||
|
NAME="WEB-AUTHENTICATION"
|
||
|
></A
|
||
|
>11.2. Authenticating on the Web</H1
|
||
|
><P
|
||
|
>On the web, a web server is usually authenticated to users by using SSL or TLS
|
||
|
and a server certificate - but it's not as easy to authenticate who
|
||
|
the users are.
|
||
|
SSL and TLS do support client-side certificates, but there are many practical
|
||
|
problems with actually using them (e.g., web browsers don't support a single
|
||
|
user certificate format and users find it difficult to install them).
|
||
|
You can learn about how to set up digital certificates from many places, e.g.,
|
||
|
<A
|
||
|
HREF="http://www.petbrain.com/modules.php?op=modload&name=pki&file=index"
|
||
|
TARGET="_top"
|
||
|
>Petbrain</A
|
||
|
>.
|
||
|
Using Java or Javascript has its own problems, since many users disable them,
|
||
|
some firewalls filter them out, and they tend to be slow.
|
||
|
In most cases, requiring every user to install a plug-in is impractical too,
|
||
|
though if the system is only for an intranet for a relatively
|
||
|
small number of users this may be appropriate.</P
|
||
|
><P
|
||
|
>If you're building an intranet application, you should generally use
|
||
|
whatever authentication system is used by your users.
|
||
|
Unix-like systems tend to use Kerberos, NIS+, or LDAP.
|
||
|
You may also need to deal with a Windows-based authentication schemes
|
||
|
(which can be viewed as proprietary variants of Kerberos and LDAP).
|
||
|
Thus, if your organization depend on Kerberos,
|
||
|
design your system to use Kerberos.
|
||
|
Try to separate the authentication system from the rest of your application,
|
||
|
since the organization may (will!) change their authentication system over
|
||
|
time.</P
|
||
|
><P
|
||
|
>Many techniques don't work or don't work very well.
|
||
|
One approach that works in some cases
|
||
|
is to use ``basic authentication'', which is built into
|
||
|
essentially all browsers and servers.
|
||
|
Unfortunately, basic authentication sends passwords unencrypted, so it
|
||
|
makes passwords easy to steal; basic authentication by itself is really
|
||
|
useful only for worthless information.
|
||
|
You could store authentication information in the URLs selected by the users,
|
||
|
but for most circumstances you should never do this - not only are
|
||
|
the URLs sent unprotected over the wire (as with basic authentication),
|
||
|
but there are too many other ways that
|
||
|
this information can leak to others
|
||
|
(e.g., through the browser history logs stored by many browsers,
|
||
|
logs of proxies, and to other web sites through the Referer: field).
|
||
|
You could wrap all communication with a web server using
|
||
|
an SSL/TLS connection (which would encrypt it); this is secure
|
||
|
(depending on how you do it), and it's
|
||
|
necessary if you have important data, but note that
|
||
|
this is costly in terms of performance.
|
||
|
You could also use ``digest authentication'', which exposes the communication
|
||
|
but at least authenticates the user without exposing the
|
||
|
underlying password used to authenticate the user.
|
||
|
Digest authentication is intended to be a simple partial solution for
|
||
|
low-value communications,
|
||
|
but digest authentication
|
||
|
is not widely supported in an interoperable way by web browsers and servers.
|
||
|
In fact, as noted in a March 18, 2002 eWeek article,
|
||
|
Microsoft's web client (Internet Explorer) and web server (IIS)
|
||
|
incorrectly implement the standard (RFC 2617), and thus won't work with
|
||
|
other servers or browsers. Since Microsoft
|
||
|
don't view this incorrect implementation as a serious
|
||
|
problem, it will be a very long time before most of their customers have
|
||
|
a correctly-working program.</P
|
||
|
><P
|
||
|
>Thus, the most common technique for authenticating on the web today is
|
||
|
through cookies.
|
||
|
Cookies weren't really designed for this purpose, but they can be used
|
||
|
for authentication - but there are many wrong ways to use them that
|
||
|
create security vulnerabilities, so be careful.
|
||
|
For more information about cookies, see IETF RFC 2965, along with the
|
||
|
older specifications about them.
|
||
|
Note that to use cookies, some browsers (e.g., Microsoft
|
||
|
Internet Explorer 6) may insist that you
|
||
|
have a privacy profile (named p3p.xml on the root directory of the server).</P
|
||
|
><P
|
||
|
>Note that some users don't accept cookies, so this solution still has
|
||
|
some problems.
|
||
|
If you want to support these users,
|
||
|
you should send this authentication information back and forth via
|
||
|
HTML form hidden fields
|
||
|
(since nearly all browsers support them without concern).
|
||
|
You'd use the same approach as with cookies - you'd just use a different
|
||
|
technology to have the data sent from the user to the server.
|
||
|
Naturally, if you implement this approach, you need to include settings to
|
||
|
ensure that these pages aren't cached for use by others.
|
||
|
However, while I think avoiding cookies
|
||
|
is preferable, in practice these other approaches often require
|
||
|
much more development effort.
|
||
|
Since it's so hard to implement this on a large scale for many
|
||
|
application developers, I'm not currently stressing these approaches.
|
||
|
I would rather describe an approach that is reasonably secure and
|
||
|
reasonably easy to implement, than emphasize approaches that are too
|
||
|
hard to implement correctly (by either developers or users).
|
||
|
However, if you can do so without much effort, by all means support
|
||
|
sending the authentication information using form hidden fields and
|
||
|
an encrypted link (e.g., SSL/TLS).
|
||
|
As with all cookies, for these cookies you
|
||
|
should turn on the HttpOnly flag unless
|
||
|
you have a web browser script that must be able to read the cookie.</P
|
||
|
><P
|
||
|
>Fu [2001] discusses client authentication on the web, along with a
|
||
|
suggested approach, and this is the approach I suggest for most sites.
|
||
|
The basic idea is that client authentication is split into two parts,
|
||
|
a ``login procedure'' and ``subsequent requests.''
|
||
|
In the login procedure, the server asks for the user's username and password,
|
||
|
the user provides them, and the server replies with an
|
||
|
``authentication token''.
|
||
|
In the subsequent requests, the client (web browser)
|
||
|
sends the authentication token
|
||
|
to the server (along with its request); the server verifies that the
|
||
|
token is valid, and if it is, services the request.
|
||
|
Another good source of information about web authentication is
|
||
|
Seifried [2001].</P
|
||
|
><P
|
||
|
>One serious problem with some web authentication techniques is that
|
||
|
they are vulnerable to a problem called "session fixation".
|
||
|
In a session fixation attack, the attacker fixes the user's session ID
|
||
|
before the user even logs into the target server, thus eliminating the
|
||
|
need to obtain the user's session ID afterwards.
|
||
|
Basically, the attacker obtains an account, and then tricks another
|
||
|
user into using the attacker's account - often by creating a special
|
||
|
hypertext link and tricking the user into clicking on it.
|
||
|
A good paper describing session fixation is the paper by
|
||
|
<A
|
||
|
HREF="http://www.acros.si/papers/session_fixation.pdf"
|
||
|
TARGET="_top"
|
||
|
>Mitja Kolsek [2002]</A
|
||
|
>.
|
||
|
A web authentication system you use should be resistant to session fixation.</P
|
||
|
><DIV
|
||
|
CLASS="SECT2"
|
||
|
><H2
|
||
|
CLASS="SECT2"
|
||
|
><A
|
||
|
NAME="WEB-AUTHENTICATION-LOGIN"
|
||
|
></A
|
||
|
>11.2.1. Authenticating on the Web: Logging In</H2
|
||
|
><P
|
||
|
>The login procedure is typically implemented as an HTML form;
|
||
|
I suggest using the field names ``username'' and ``password'' so that
|
||
|
web browsers can automatically perform some useful actions.
|
||
|
Make sure that the password is sent over an encrypted connection
|
||
|
(using SSL or TLS, through an https: connection) - otherwise, eavesdroppers
|
||
|
could collect the password.
|
||
|
Make sure all password text fields are marked as passwords in the HTML,
|
||
|
so that the password text is not visible to
|
||
|
anyone who can see the user's screen.</P
|
||
|
><P
|
||
|
>If both the username and password fields are filled in,
|
||
|
do not try to automatically log in as that user.
|
||
|
Instead, display the login form with the user and password fields;
|
||
|
this lets the user verify that they really want to log in as that user.
|
||
|
If you fail to do this, attackers will be able to exploit this weakness to
|
||
|
perform a session fixation attack.
|
||
|
Paranoid systems might want simply ignore the password field and make the
|
||
|
user fill it in, but this interferes with browsers which can store
|
||
|
passwords for users.</P
|
||
|
><P
|
||
|
>When the user sends username and password, it must be checked against
|
||
|
the user account database.
|
||
|
This database shouldn't store the passwords ``in the clear'', since if
|
||
|
someone got a copy of the this database they'd suddenly get everyone's
|
||
|
password (and users often reuse passwords).
|
||
|
Some use crypt() to handle this, but crypt can only handle a small
|
||
|
input, so I recommend using a different approach (this is my approach -
|
||
|
Fu [2001] doesn't discuss this).
|
||
|
Instead, the user database should store a username, salt, and
|
||
|
the password hash for that user.
|
||
|
The ``salt'' is just a random sequence of characters, used to make it
|
||
|
harder for attackers to determine a password even if they get the
|
||
|
password database - I suggest an 8-character random sequence.
|
||
|
It doesn't need to be cryptographically random, just different from
|
||
|
other users.
|
||
|
The password hash should be computed by concatenating
|
||
|
``server key1'', the user's password, and the salt, and
|
||
|
then running a cryptographically secure hash algorithm.
|
||
|
Server key1 is a secret key unique to this server - keep it separate
|
||
|
from the password database.
|
||
|
Someone who has server key1 could then run programs to crack user
|
||
|
passwords if they also had the password database;
|
||
|
since it doesn't need to be memorized, it can be a long and complex
|
||
|
password.
|
||
|
Most secure would be HMAC-SHA-1 or HMAC-MD5;
|
||
|
you could use SHA-1 (most web sites aren't really worried about
|
||
|
the attacks it allows) or MD5 (but MD5 would be poorer choice;
|
||
|
see the discussion about MD5).</P
|
||
|
><P
|
||
|
>Thus, when users create their accounts, the password is hashed and
|
||
|
placed in the password database.
|
||
|
When users try to log in, the purported password is hashed and compared
|
||
|
against the hash in the database (they must be equal).
|
||
|
When users change their password, they should type in both the old
|
||
|
and new password, and the new password twice (to make sure they didn't
|
||
|
mistype it); and again, make sure none of these password's characters
|
||
|
are visible on the screen.</P
|
||
|
><P
|
||
|
>By default, don't save the passwords themselves on the client's
|
||
|
web browser using cookies - users may sometimes use shared clients
|
||
|
(say at some coffee shop).
|
||
|
If you want, you can give users the option of ``saving the password''
|
||
|
on their browser, but if you do, make sure that the password is set to
|
||
|
only be transmitted on ``secure'' connections, and make sure the user has
|
||
|
to specifically request it (don't do this by default).</P
|
||
|
><P
|
||
|
>Make sure that the page is marked to not be cached, or a proxy
|
||
|
server might re-serve that page to other users.</P
|
||
|
><P
|
||
|
>Once a user successfully logs in, the server needs to send the client
|
||
|
an ``authentication token'' in a cookie, which is described next.</P
|
||
|
></DIV
|
||
|
><DIV
|
||
|
CLASS="SECT2"
|
||
|
><H2
|
||
|
CLASS="SECT2"
|
||
|
><A
|
||
|
NAME="WEB-AUTHENTICATION-SUBSEQUENT"
|
||
|
></A
|
||
|
>11.2.2. Authenticating on the Web: Subsequent Actions</H2
|
||
|
><P
|
||
|
>Once a user logs in, the server sends back to the client a cookie
|
||
|
with an authentication token that will be used from then on.
|
||
|
A separate authentication token is used, so that users don't need to keep
|
||
|
logging in, so that passwords aren't continually sent back and forth, and
|
||
|
so that unencrypted communication can be used if desired.
|
||
|
A suggested token (ignoring session fixation attacks) would look like this:
|
||
|
<TABLE
|
||
|
BORDER="0"
|
||
|
BGCOLOR="#E0E0E0"
|
||
|
WIDTH="100%"
|
||
|
><TR
|
||
|
><TD
|
||
|
><FONT
|
||
|
COLOR="#000000"
|
||
|
><PRE
|
||
|
CLASS="PROGRAMLISTING"
|
||
|
> exp=t&data=s&digest=m</PRE
|
||
|
></FONT
|
||
|
></TD
|
||
|
></TR
|
||
|
></TABLE
|
||
|
>
|
||
|
Where t is the expiration time of the token (say, in several hours),
|
||
|
and data s identifies the user (say, the user name or session id).
|
||
|
The digest is a keyed digest of the other fields.
|
||
|
Feel free to change the field name of ``data'' to be more descriptive
|
||
|
(e.g., username and/or sessionid).
|
||
|
If you have more than one field of data (e.g., both a username and a
|
||
|
sessionid), make sure the digest uses both the field names and data values
|
||
|
of all fields you're authenticating; concatenate them with a pattern
|
||
|
(say ``%%'', ``+'', or ``&'')
|
||
|
that can't occur in any of the field data values.
|
||
|
As described in a moment, it would be a good idea to include a username.
|
||
|
The keyed digest should be a cryptographic hash of the other information in
|
||
|
the token, keyed using a different server key2.
|
||
|
The keyed digest should use HMAC-MD5 or HMAC-SHA1, using a different server
|
||
|
key (key2), though simply using SHA1 might be okay for some purposes
|
||
|
(or even MD5, if the risks are low).
|
||
|
Key2 is subject to brute force guessing attacks, so it should be
|
||
|
long (say 12+ characters) and unguessable; it does NOT need to be easily
|
||
|
remembered.
|
||
|
If this key2 is compromised, anyone can authenticate to the server, but
|
||
|
it's easy to change key2 - when you do, it'll simply force currently
|
||
|
``logged in'' users to re-authenticate.
|
||
|
See Fu [2001] for more details.</P
|
||
|
><P
|
||
|
>There is a potential weakness in this approach.
|
||
|
I have concerns that Fu's approach, as originally described, is weak against
|
||
|
session fixation attacks (from several different directions, which
|
||
|
I don't want to get into here).
|
||
|
Thus, I now suggest modifying Fu's approach and using this token format
|
||
|
instead:
|
||
|
<TABLE
|
||
|
BORDER="0"
|
||
|
BGCOLOR="#E0E0E0"
|
||
|
WIDTH="100%"
|
||
|
><TR
|
||
|
><TD
|
||
|
><FONT
|
||
|
COLOR="#000000"
|
||
|
><PRE
|
||
|
CLASS="PROGRAMLISTING"
|
||
|
> exp=t&data=s&client=c&digest=m</PRE
|
||
|
></FONT
|
||
|
></TD
|
||
|
></TR
|
||
|
></TABLE
|
||
|
>
|
||
|
This is the same as the original Fu aproach, and older versions of
|
||
|
this book (before December 2002) didn't suggest it.
|
||
|
This modification adds a new
|
||
|
"client" field to uniquely identify the client's current location/identity.
|
||
|
The data in the client field should be something that should change
|
||
|
if someone else tries to use the account; ideally, its new value should be
|
||
|
unguessable, though that's hard to accomplish in practice.
|
||
|
Ideally the client field would be the client's SSL client certificate,
|
||
|
but currently that's a suggest that is hard to meet.
|
||
|
At the least, it should be the user's IP address (as perceived from
|
||
|
the server, and remember to plan for IPv6's longer addresses).
|
||
|
This modification doesn't completely counter session fixation attacks,
|
||
|
unfortunately (since if an attacker can determine what the user
|
||
|
would send, the attacker may be able to make a request to a server
|
||
|
and convince the client to accept those values).
|
||
|
However, it does add resistance to the attack.
|
||
|
Again, the digest must now include all the other data.</P
|
||
|
><P
|
||
|
>Here's an example.
|
||
|
If a user logs into foobar.com sucessfully, you might establish
|
||
|
the expiration date as 2002-12-30T1800 (let's assume we'll transmit as
|
||
|
ASCII text in this format for the moment), the username as "fred",
|
||
|
the client session as "1234", and you might determine that the
|
||
|
client's IP address was 5.6.7.8.
|
||
|
If you use a simple SHA-1 keyed digest
|
||
|
(and use a key prefixing the rest of the data), with the server key2 value of
|
||
|
"rM!V^m~v*Dzx", the digest could be computed over:
|
||
|
<TABLE
|
||
|
BORDER="0"
|
||
|
BGCOLOR="#E0E0E0"
|
||
|
WIDTH="100%"
|
||
|
><TR
|
||
|
><TD
|
||
|
><FONT
|
||
|
COLOR="#000000"
|
||
|
><PRE
|
||
|
CLASS="PROGRAMLISTING"
|
||
|
> exp=2002-12-30T1800&user=fred&session=1234&client=5.6.7.8</PRE
|
||
|
></FONT
|
||
|
></TD
|
||
|
></TR
|
||
|
></TABLE
|
||
|
>
|
||
|
A keyed digest can be computed by running a cryptographic hash code
|
||
|
over, say, the server key2, then the data;
|
||
|
in this case, the digest would be:
|
||
|
<TABLE
|
||
|
BORDER="0"
|
||
|
BGCOLOR="#E0E0E0"
|
||
|
WIDTH="100%"
|
||
|
><TR
|
||
|
><TD
|
||
|
><FONT
|
||
|
COLOR="#000000"
|
||
|
><PRE
|
||
|
CLASS="PROGRAMLISTING"
|
||
|
>101cebfcc6ff86bc483e0538f616e9f5e9894d94</PRE
|
||
|
></FONT
|
||
|
></TD
|
||
|
></TR
|
||
|
></TABLE
|
||
|
></P
|
||
|
><P
|
||
|
>From then on, the server must check the expiration time and recompute the
|
||
|
digest of this authentication token, and only accept client requests
|
||
|
if the digest is correct.
|
||
|
If there's no token, the server should reply with the user login page
|
||
|
(with a hidden form field to show where the successful login should go
|
||
|
afterwards).</P
|
||
|
><P
|
||
|
>It would be prudent to display the username, especially on important
|
||
|
screens, to help counter session fixation attacks.
|
||
|
If users are given feedback on their username, they may notice if they
|
||
|
don't have their expected username. This is helpful anyway if it's
|
||
|
possible to have an unexpected username (e.g., a family that shares the
|
||
|
same machine).
|
||
|
Examples of important screens include those when a file is uploaded
|
||
|
that should be kept private.</P
|
||
|
><P
|
||
|
>One odd implementation issue: although the specifications for the
|
||
|
"Expires:" (expiration time) field for cookies
|
||
|
permit time zones, it turns out that some versions of
|
||
|
Microsoft's Internet Explorer don't implement time zones correctly
|
||
|
for cookie expiration.
|
||
|
Thus, you need to always use UTC time (also called Zulu time)
|
||
|
in cookie expiration times for maximum portability.
|
||
|
It's a good idea in general to use UTC time for time values,
|
||
|
and convert when necessary for human display, since this eliminates other
|
||
|
time zone and daylight savings time issues.</P
|
||
|
><P
|
||
|
>If you include a sessionid in the authentication token, you can limit
|
||
|
access further.
|
||
|
Your server could ``track'' what pages a user has seen in a given session,
|
||
|
and only permit access to other appropriate pages from that point
|
||
|
(e.g., only those directly linked from those page(s)).
|
||
|
For example,
|
||
|
if a user is granted access to page foo.html, and page foo.html has
|
||
|
pointers to resources bar1.jpg and bar2.png, then accesses to bar4.cgi
|
||
|
can be rejected.
|
||
|
You could even kill the session, though only do this if the authentication
|
||
|
information is valid (otherwise, this would make it possible for
|
||
|
attackers to cause denial-of-service attacks on other users).
|
||
|
This would somewhat limit the access an attacker has, even if they
|
||
|
successfully hijack a session, though clearly an attacker with time
|
||
|
and an authentication token
|
||
|
could ``walk'' the links just as a normal user would.</P
|
||
|
><P
|
||
|
>One decision is whether or not to require the authentication token and/or
|
||
|
data to be sent over a secure connection (e.g., SSL).
|
||
|
If you send an authentication token
|
||
|
in the clear (non-secure), someone who intercepts the
|
||
|
token could do whatever the user could do until the expiration time.
|
||
|
Also, when you send data over an unencrypted link, there's the risk of
|
||
|
unnoticed change by an attacker; if you're worried that someone might change the
|
||
|
data on the way, then you need to authenticate the data being transmitted.
|
||
|
Encryption by itself doesn't guarantee authentication, but it does make
|
||
|
corruption more likely to be detected, and typical libraries can support
|
||
|
both encryption and authentication in a TLS/SSL connection.
|
||
|
In general, if you're encrypting a message, you should also authenticate it.
|
||
|
If your needs vary,
|
||
|
one alternative is to create two authentication tokens - one is used
|
||
|
only in a ``secure'' connection for important operations, while the other
|
||
|
used for less-critical operations.
|
||
|
Make sure the token used for ``secure'' connections is marked so that only
|
||
|
secure connections (typically encrypted SSL/TLS connections) are used.
|
||
|
If users aren't really different, the authentication token could omit
|
||
|
the ``data'' entirely.</P
|
||
|
><P
|
||
|
>Again, make sure that the pages with this authentication token aren't cached.
|
||
|
There are other reasonable schemes also; the goal of this text is
|
||
|
to provide at least one secure solution.
|
||
|
Many variations are possible.</P
|
||
|
></DIV
|
||
|
><DIV
|
||
|
CLASS="SECT2"
|
||
|
><H2
|
||
|
CLASS="SECT2"
|
||
|
><A
|
||
|
NAME="WEB-AUTHENTICATION-LOGOUT"
|
||
|
></A
|
||
|
>11.2.3. Authenticating on the Web: Logging Out</H2
|
||
|
><P
|
||
|
>You should always provide users with a mechanism to ``log out'' - this
|
||
|
is especially helpful for customers using shared browsers
|
||
|
(say at a library).
|
||
|
Your ``logout'' routine's task is simple - just unset the client's
|
||
|
authentication token.</P
|
||
|
></DIV
|
||
|
></DIV
|
||
|
><DIV
|
||
|
CLASS="NAVFOOTER"
|
||
|
><HR
|
||
|
ALIGN="LEFT"
|
||
|
WIDTH="100%"><TABLE
|
||
|
SUMMARY="Footer navigation table"
|
||
|
WIDTH="100%"
|
||
|
BORDER="0"
|
||
|
CELLPADDING="0"
|
||
|
CELLSPACING="0"
|
||
|
><TR
|
||
|
><TD
|
||
|
WIDTH="33%"
|
||
|
ALIGN="left"
|
||
|
VALIGN="top"
|
||
|
><A
|
||
|
HREF="passwords.html"
|
||
|
ACCESSKEY="P"
|
||
|
>Prev</A
|
||
|
></TD
|
||
|
><TD
|
||
|
WIDTH="34%"
|
||
|
ALIGN="center"
|
||
|
VALIGN="top"
|
||
|
><A
|
||
|
HREF="index.html"
|
||
|
ACCESSKEY="H"
|
||
|
>Home</A
|
||
|
></TD
|
||
|
><TD
|
||
|
WIDTH="33%"
|
||
|
ALIGN="right"
|
||
|
VALIGN="top"
|
||
|
><A
|
||
|
HREF="random-numbers.html"
|
||
|
ACCESSKEY="N"
|
||
|
>Next</A
|
||
|
></TD
|
||
|
></TR
|
||
|
><TR
|
||
|
><TD
|
||
|
WIDTH="33%"
|
||
|
ALIGN="left"
|
||
|
VALIGN="top"
|
||
|
>Passwords</TD
|
||
|
><TD
|
||
|
WIDTH="34%"
|
||
|
ALIGN="center"
|
||
|
VALIGN="top"
|
||
|
><A
|
||
|
HREF="special.html"
|
||
|
ACCESSKEY="U"
|
||
|
>Up</A
|
||
|
></TD
|
||
|
><TD
|
||
|
WIDTH="33%"
|
||
|
ALIGN="right"
|
||
|
VALIGN="top"
|
||
|
>Random Numbers</TD
|
||
|
></TR
|
||
|
></TABLE
|
||
|
></DIV
|
||
|
></BODY
|
||
|
></HTML
|
||
|
>
|