All interactions between the UA and WAS SHOULD be SSL-protected, to prevent cookies being disclosed to an eavesdropper that could use those cookies to impersonate a user.
Although support will initially be provided only for Apache 2.0, it should be possible to support the protocol under other application servers, such as a Java application server (not running under Apache), and other servers like IIS. The protocol is also being designed so it doesn't require Kerberos V5 support, which should aid in making it flexible to port to other application servers, and support future standards as they arise.
All interactions between the UA and WebKDC MUST be protected via SSL to prevent disclosure of passwords, as well as sensitive data such as the tokens which are used to provide single sign-on and access to application resources.
The WebKDC will listen for two different type of requests, which will most likely be distinguished by different URLs.
The first type of request are those requests coming from a UA after it has been redirected by a WAS. When the WebKDC receives one of these, it will first see if the request includes a cookie that contains cached credentials. If the request contains a valid cookie, this cookie is used to obtain a new credentials and the user is redirected back to the WAS.
If the cookie is not present or has expired, then the user will be prompted for their username and password. After submitting this information back to the WebKDC, the WebKDC will then verify the username and password, using the configured authenticated backend (Kerberos V5 by default). The WebKDC will the generate two "tokens". One is placed in a cookie scoped for the WebKDC and used to provide single sign-on in future requests, and one that gets sent back to the WAS, which will verify it upon receipt.
The second type of the WebKDC handles consist of XML messages that get POSTed to the WebKDC via HTTPS directly from a WAS. These message are used to request additional credentials for a user.
The WebKDC is also responsible for ensuring that the server making a request is authorized to make the request. For example, one WAS server can't use a "token" that was created for use by another WAS server.
Tokens provide a standard mechanism to exchange and store information that is cryptographically secure from both tampering and disclosure. Tokens also contain information such as creation times to help detect replays, and expiration times so data is never trusted/used forever. Tokens also enable authentication of the servers using them.
Tokens get transfered between servers using URL query parameters, POST data, cookies, and XML documents. They are AES-encrypted using either a private key, or a shared session key. They also include a SHA1 HMAC used to detect data modification/tampering.
There are currently nine different type of tokens, which are described in the following table.
Token Type | Encrypted With | Description |
---|---|---|
webkdc-service | WebKDC's private AES-key |
The webkdc-service-token is used by WebAuth App Servers to communicate
with the WebKDC. It contains a session key that is shared between
the WebKDC and the WAS.
webkdc-service-tokens are created only by the WebKDC, and are used only by a WAS. |
webkdc-proxy | WebKDC's private AES-key | The webkdc-proxy-token contains a user's proxied credentials (K5/K4 tgt). The WebKDC will only allow a webkdc-proxy-token to be used by the server it was originally generated for. The main use of a webkdc-proxy-token is by the WebKDC itself to implement single sign-on. Its secondary use is to allow WAS servers to request credential-tokens. |
request | session-key | The request-token contains the request from a WAS for a token (usually an id-token) from the WebKDC. It is AES-encrypted in a session-key from a webkdc-service-token, and contains information like the return URL, type of token requested, etc. A webkdc-service-token is always included along with a request-token. |
error | session-key | The error-token is returned in the event of an unrecoverable error that occurred while asking for a token with a request-token. |
id | session-key | The id-token contains the identity of the user trying to access a resource. The WAS will verify the id-token, then construct an app-token for future use. |
proxy | session-key | The proxy-token is used to return a webkdc-proxy-token to a WAS. It includes information about the webkdc-proxy-token, such as its expiration, its type, etc. |
cred | session-key | The credential-token contains a user's credential (K5/K4 service ticket). |
login | WebKDC's private AES-key | login-tokens are used by the WebKDC with the requestTokenRequest command. They contain the user's username and password and are used to obtain the inital webkdc-proxy-tokens. |
app | WAS private AES-key | app-tokens are used by WAS servers to store data, such as the identity of a user after it has been verified from an id-token, a proxy-token, or credentials for future use. |
Their exact formats are discussed in detail at the end of this document.
As mentioned in the previous section, tokens are at the heart of the WebAuth security model. They are used to authenticate requests and responses between servers, as well as protect data that is stored in URLs and cookie data. Shared symmetric keys (session-keys) are used to encrypt tokens between servers, and private keys are used to encrypt tokens meant for a only a single server to decrypt.
Also note that any tokens that appear in URLs are tokens that are only valid for a short-period of time (5 minutes by default).
Any attempt to re-use them after that will fail. If a user bookmarks a URL with a token in it (or hits their "back" button) then one of three things can happen:
In order to exchange session-keys, a key distribution protocol is needed. For this purpose, we use Kerberos V5 and SSL to bootstrap and get the session-keys. The WAS that needs a session-key will post an XML message to the WebKDC requesting a service-token. This message contains the result of krb5_mk_req call for the WebKDC's server principal, which the WebKDC uses to authenticate the server making the request. The WebKDC will then send back the service-token, and the session-key that is encrypted (in the WebKDC's key) inside of the service-token. The WAS will need both to make future requests to the WebKDC. The whole transaction itself is protected with SSL.
The thing to note here is that there are no long term keys stored on the WebKDC itself other its own private key. Once the WAS obtains the service-token and session-key, it will cache them both until the service-token expires, which will most likely be 24 hours. Before the service-token expires, the WAS must request a new service-token.
The protocol is also designed such that other authentication mechanisms may be used to bootstrap, such as the GSS-API, or SSL client authentication between servers.
One potential issue here is that we are using weaker DES keys (Kerberos V5 keytabs) to bootstrap into stronger AES keys. This issue is partially mitigated by the use of SSL to further protect the transaction. It was decided that this was acceptable in order to keep the WebKDC stateless and to re-use the existing Kerberos V5 infrastructure where possible.
Both the WebKDC and the WAS servers need private keys to encrypt their tokens with. These keys will be randomly-generated 128-bit AES keys (longer keys are supported if needed), that get stored in "key rings". The key ring is used to contain previously valid keys, currently valid keys, and keys that will be valid in the future. A command-line utility is provided to manage the key ring file.
The key ring consists of a number of entries, each of which contain the following information:
key type Type of the key, AES is the only supported key type right now. key data The binary data that makes up the key creation Time the key was created valid_after When the key becomes valid
Of note is the "valid_after" value. It is used to create post-dated keys in the key ring, to allow for new keys to get generated and distributed among a pool of servers (for load balancing/fail-over) in such a way that all the keys can be updated before the key becomes valid.
Initially key rings can be distributed using a mechanism like SSH, though there will eventually be support within the WebAuth protocol for distributing new key rings among a pool of servers.
Stand-alone servers (not part of a pool) will automatically generate new keys when needed upon a restart.
In order to support server pools, we need to ensure that any server that receives a token is able to decrypt and verify it. Note that we are only talking about the WebAuth protocol here, applications must solve their own issues when dealing with a pool of servers.
For the WebKDC, all we need to do is distribute the key ring file across all the WebKDCs, and having a posted-dated new key in the key ring file makes this task easier.
For the WAS, there are two issues. First, we also need to distribute the key ring file so all WAS servers can decrypt their app-tokens. The second issue, is how to deal with session-keys.
Recall that responses from the WebKDC come back to the WAS encrypted in the session-key, not the WAS server's private key. If the response comes back to a different WAS server, it would not have the same session-key that another WAS server had. One way to deal with session-keys would be to share the same service-token and session-key across all the servers. This of course would be very painful and expensive to do.
Another way to handle this is make sure that the return-url in the request-token contains the real server's hostname/ip address as opposed to the virtual/pool address. This solves the problem as the request always comes back to WAS server that initiated the request. This approach however might not work in all environments. For example, the real app server's address may not be visible from outside the firewall.
The most flexible solution is to allow WAS servers to include some "state" or "context" in each request-token. The WebKDC would treat this state as opaque data, and return it to the WAS server along with the requested token. Note that it would be transmitted alongside the returned token, not inside of it. Now, the WAS server would create an app-token (which is encrypted in its private key), that contains the session-key, and use this as the state it sends in the request-token. The WebKDC return this state along with the response, and the WAS can decrypt the state using its private key to get the session-key.
--------------------------------------------------------------- UA WAS WebKDC --------------------------------------------------------------- request resource 1. -----------------> WAS redirect to WebKDC 2. <----------------- WAS request-token for id-token 3. -------------------------------> WebKDC login form gets sent back 4. <------------------------------- WebKDC login form gets posted 5. -------------------------------> WebKDC confirmation page gets sent back 6. <------------------------------- WebKDC re-request resource (with returned token in URL) 7. -----------------> WAS set the app-token cookie, response from app 8. <----------------- WAS ---------------------------------------------------------------We will now go over each step in detail.
mod_webauth then generates a redirect to the WebKDC (including the request-token in the URL query parameters).
The WebKDC validates the username/password, and also makes sure the that the WAS is allowed to request identity tokens.
Assuming the username/password is valid, the WebKDC will then construct a cookie for itself, which contains the proxy-token, and the id-token.
A confirmation page will be sent back to the browser, that when ok'd will do a GET on the original request, with the id-token appended to the original request.
After verifying the subject, mod_webauth will then rewrite the id-token into an app-token, and create an app-token to be placed into a cookie for future requests.
mod_webauth will then strip off the token from the URL, and let the original app handle the request. Note that the tokens will not show up in the access_log.
--------------------------------------------------------------- UA WAS WebKDC --------------------------------------------------------------- request resource 1. -----------------> WAS response 2. <----------------- WAS ---------------------------------------------------------------We will now go over each step in detail.
This is the "Single Sign-on" case, because the WebKDC can use the user's proxy-token to acquire access to the application without having to prompt the user for their password again.
--------------------------------------------------------------- UA WAS WebKDC --------------------------------------------------------------- request resource 1. -----------------> WAS redirect to WebKDC 2. <----------------- WAS request-token for id-token 3. -------------------------------> WebKDC redirect with returned token 4. <------------------------------- WebKDC re-request resource (with returned token in URL) 5. -----------------> WAS set the app-token cookie, response from app 6. <----------------- WASWe will now go over each step in detail.
mod_webauth then generates a redirect to the WebKDC (including the request-token in the URL query parameters).
After verifying the subject, mod_webauth will then rewrite the id-token into an app-token, and create an app-token to be placed into a cookie for future requests.
mod_webauth will then strip off the token from the URL, and let the original app handle the request.
This is the "Proxy credentials" case. The WAS must request a proxy-token, which it will then use to request additional credentials via the XML interface. In this scenario we assume the WebKDC already has a proxy-token for itself.
--------------------------------------------------------------- UA WAS WebKDC --------------------------------------------------------------- request resource 1. -----------------> WAS redirect to WebKDC 2. <----------------- WAS request-token for proxy-token 3. ------------------------------------> WebKDC redirect with returned token 4. <------------------------------------ WebKDC re-request resource (with returned token in URL) 5. -----------------> WAS request tokens 6. WAS -------------> WebKDC response 7. WAS <------------- WebKDC set the cookies, response from app 8. <----------------- WASWe will now go over each step in detail.
mod_webauth then generates a redirect to the WebKDC (including the request-token in the URL query parameters).
After verifying the id-token, mod_webauth will then rewrite the id-token into an app-token, and also re-encrypt the credential token(s) using its private key. All the tokens will be placed into cookies for future requests. The proxy-token can be discarded.
mod_webauth will then strip off the token from the URL, and let the original app handle the request.
The credentials will be passed to the application by having mod_webauth save the credentials into a ticket file, and setting an environment variable to point to that ticket file. When the credential file gets created will most likely be based upon an Apache directive. Note: this needs to be looked at in more detail, and other options may be needed.
Aside from quitting the browser, there are two issues to consider when logging out:
mod_webauth can also be configured to send the user to a system-wide logout page on the WebKDC. This would create a more consistent logout experience for users. The logout page could also remind the user that they may be logged into other applications well, and could also have them click on a link to destroy their proxy-token as well.
It will also be possible for the application to specify a session timeout, such that app-tokens will become invalid if they aren't used within a certain period of time. This can also be combined with an option that causes the application to request that the proxy-token be ignored, effectively forcing the user to sign in again.
Note that its not possible for the WebKDC to remove individual app-token cookies, since those cookies are scoped to each application server.
Each WAS will be configured with a URL to redirect a UA to in the event they need to make a request. When making the request, the WAS must include both the request-token and the webkdc-service-token (so the WebKDC can decrypt the request-token).
These tokens will be passed via query parameters in the URL. The format is:
https://{webkdc-host}/{webkdc-login-uri}?RT=request-token;ST=service-token
Where RT is the base64-encoded request-token and ST is the base64-encoded service-token.
When the WebKDC is ready to redirect the UA back to the WAS, it will construct a return URL by taking the return-url specified in the request token an appending "?WEBAUTHR=token;" to it, where token is the requested token. If the "as" attribute was specified in the request token, then it is base64-encoded and then appended to the URL (always after WEBAUTHR) as ";WEBAUTHS=token;".
For example:
https://{return-url}?WEBAUTHR=token;[;WEBAUTHS=token;]
The WebAuth Apache module will then strip "?WEBAUTHR=token;" and ";WEBAUTHS=token;" off the end of the URL. If the tokens are valid, the WebAuth module will construct the app-token cookie, etc, then do another redirect back to the URL with the extra information stripped off.
The protocol consists of an exchange of XML-formatted messages over a tcp-based connection. A protocol interaction consists of a single XML message from the client and a single XML message response from the server.
For any elements that require a base64-encoded value, there must be no whitespace after the open element and before the close element. For example, this is valid:
<requestToken>{base64-webkdc-service-token}</requestToken>
while this is not:
<requestToken>
{base64-webkdc-service-token}
</requestToken>
Having said that, this spec uses whitespace in examples for readability.
The message is posted to the WebKDC using HTTPS.
The command request format is:
<xxxxRequest>
<messageId>{message-id}</messageId> <!-- optional, no default -->
<protocolVersion>1</protocolVersion> <!-- optional, default is 1 -->
<!-- rest depends on command -->
</xxxxRequest>
The command response format on success is:
<xxxxResponse>
<messageId>{message-id}</messageId> <!-- only if present in request -->
<!-- rest depends on command -->
</xxxxResponse>
The command response format on failure is:
<errorResponse>
<messageId>{message-id}</messageId> <!-- only if present in request -->
<errorCode>{numeric}<errorCode>
<errorMessage>{message}<errorMessage>
</errorResponse>
Error Code | Description |
---|---|
1 | The service-token used was expired. |
2 | The service-token used was corrupt and/or was unable to be decrypted. |
3 | The proxy-token used was expired. |
4 | The proxy-token used was corrupt and/or was unable to be decrypted. |
5 | The request was invalid. For example, a required element was missing, an attribute value was incorrect, the server was unable to parse the XML request, etc. The generally indicates a bug in the client. |
6 | The request was unauthorized. An attempt was made to request a token type that was not authorized. |
7 | The server had an internal error (out of memory, etc). If the client retries the request may succeed, though some external event might be causing the problem (Kerberos server being down, etc). |
8 | The request-token was stale. |
9 | The request-token was invalid. |
10 | Unable to obtain the requested credential. |
11 | The krb5 <requesterCredential> was bad. |
12 | The login-token was stale. |
13 | The login-token was invalid. |
14 | Login failed due to bad password or invalid username. |
15 | A webkdc-proxy-token of a certain type was required and was not present in the request. |
16 | The user hit the cancel button during the login process. |
17 | The WAS server requested a "forced" login. |
The request message is:
<getTokensRequest>
<requesterCredential type="service|krb5">
<!-- for type="service" -->
{base64-webkdc-service-token}
<!-- for type="krb5" -->
{base64-krb5-mk-req-data}
</requesterCredential>
<subjectCredential type="proxy">
<proxyToken>{base64-webkdc-proxy-token}</proxyToken>
<!-- additional <proxyToken>...</proxyToken> here -->
</subjectCredential>
<!-- present when requestCredential is of type="service" -->
<requestToken>{base64-request-token}</requestToken>
<tokens>
<token type="id|proxy|service|cred" id="{id-to-use-in-response}">
<!-- for type="id" -->
<authenticator type="krb5|webkdc"/> <!-- optional, default is krb5 -->
<!-- for type="proxy" -->
<proxyType>krb5|krb4</proxyType>
<!-- for type="cred" -->
<credentialType>krb5|krb4</credentialType>
<serverPrincipal>{krb4/krb5-service}</serverPrincipal>
</token>
<!-- additional <token>...</token> requests go here -->
</tokens>
</getTokensRequest>
The response message is:
<getTokensResponse>
<tokens>
<token id="{id-from-request}">
<tokenData>{base64}</tokenData>
<!-- for type="service" -->
<sessionKey>{base64-session-key}</sessionKey>
<expires>{expiration-time}</expires>
</token>
<!-- additional <token>...</token> responses go here -->
</tokens>
</getTokensResponse>
If any errors occur, then an <errorResponse> message will be returned.
requesterCredentials of type "krb5" can only be used to obtain a service-token, they can't be used for obtaining any other tokens, nor can a credential of type "service" be used to request another service-token.
subjectCredentials are required when requesting id, proxy, or cred tokens.
The request message is:
<requestTokenRequest>
<requesterCredential type="service">
{base64-webkdc-service-token}
</requesterCredential>
<subjectCredential type="proxy|login">
<!-- for type="proxy" -->
<!-- need to pass in all the existing proxy-tokens, since
we (the web front-end) don't know which we might need -->
<proxyToken>...</proxyToken>
<!-- additional <proxyToken>...</proxyToken> here -->
<!-- for type="login" -->
<loginToken>...</loginToken>
</subjectCredential>
<!-- request token from WAS -->
<requestToken>{base64-request-token}</requestToken>
<!-- request info from front-end, used with S/Ident support -->
<requestInfo>
<localIpAddr>n.n.n.n</localIpAddr>
<localIpPort>nnnn</localIpPort>
<remoteIpAddr>n.n.n.n</remoteIpAddr>
<remoteIpPort>nnnn</remoteIport>
</requestInfo>
</requestTokenRequest>
The response message is:
<requestTokenResponse>
<!-- loginErrorCode will be set in a requestTokenResponse if
there was an error related to logging in -->
<loginErrorCode>{numeric}<loginErrorCode>
<loginErrorMessage>{message}<loginErrorMessage>
<!-- any updated/new proxy tokens created, only passed back
if subjectCredential was type="login" -->
<proxyTokens>
<proxyToken type="...">{base64-proxy-token}</proxyToken>
</proxyTokens>
<!-- the url to return to the user to -->
<returnUrl>...</returnUrl>
<!-- subject inside of service-token used to make request -->
<requesterSubject>...</requesterSubject>
<!-- subject from subjectCredential -->
<subject>...</subject>
<!-- requestedToken will either be an error, id, or proxy token.
not set if <loginErrorCode> is set. -->
<requestedToken>{base64-token}</requestedToken>
<!-- set if request token request options has "lc" -->
<loginCanceledToken>{base64-error-token}</loginCanceledToken>
<!-- app state is the opaque app state passed in the
request token that we hand back to WAS -->
<appState>{base64-state}</appState>
</requestTokenResponse>
If any non login-related errors occur, then an <errorResponse> message will be returned.
If a login-related error occurs then a <requestTokenResponse> will be returned, but <requestedToken> will be unset, and <loginErrorCode> will be set. The error codes used by <loginErrorCode> are a subset of those used by <errorCode>:
Error Code | Description |
---|---|
14 | Login failed due to bad password or invalid username. The web front-end should re-prompt for username/password. |
15 | A webkdc-proxy-token of a certain type was required and was not present in the request. The web front-end should prompt for the username and password. |
17 | The WAS server requested a "forced" login. The web front-end should prompt for the username and password. |
If the request option attribute in the request token has "lc" in it, then <loginCanceledToken> will be returned. Note that it is up to the WebKDC web front-end to send back that token as the requested token (WEBAUTHR in the return URL) if the user hits the cancel button.
If the request option attribute in the request token has "fa" in it and we are not passing a login token, then this command will return a <loginErrorCode> of 17, which indicates that the user is being forced to (re)login. Any passed in proxy-tokens are ignored.
The request message is:
<webkdcProxyTokenRequest>
<subjectCredential type="krb5">
<!-- for type="krb5" -->
{base64-krb5-mk-req-data}
</subjectCredential>
<proxyData>
<!-- for subjectCredential type="krb5" -->
{base64-krb5-mk-priv-on-tgt}
</proxyData>
</webkdcProxyTokenRequest>
The response message is:
<webkdcProxyTokenResponse>
<webkdcProxyToken>{base64-proxy-token}</webkdcProxyToken>
<!-- subject from subjectCredential -->
<subject>...</subject>
</webkdcProxyTokenResponse>
If any errors occur an <errorResponse> message will be returned.
The request message is:
<webkdcProxyTokenInfoRequest>
<webkdcProxyToken>{base64-proxy-token}</webkdcProxyToken>
</webkdcProxyTokenRequest>
The response message is:
<webkdcProxyTokenInfoResponse>
<subject>...</subject>
<proxyType>...</proxyType>
<creationTime>...</creationTime>
<expirationTime>...</expirationTime>
</webkdcProxyTokenInfoResponse>
If any errors occur an <errorResponse> message will be returned.
https://{webkdc-server}/webkdc-service/
The Content-Type
should be "text/xml".
Initially only SSL will be supported. If performance becomes a concern, a non-ssl port may be opened up, in which case the content will need to be encrypted, most likely using AES.
<getTokensRequest>
<requesterCredential type="krb5">
{base64-krb5-mk-req-data}
</requesterCredential>
<tokens>
<token type="service" id="0"/>
</tokens>
</getTokensRequest>
<getTokensResponse>
<tokens>
<token id="0">
<sessionKey>{base64-session-key}</sessionKey>
<expires>{expiration-time}</expires>
<tokenData>{base64}</tokenData>
</token>
</tokens>
</getTokensResponse>
<getTokensRequest>
<requesterCredential type="service">
{base64-webkdc-service-token}
</requesterCredential>
<requestToken>{base64-request-token}</requestToken>
<subjectCredential type="proxy">
{webkdc-proxy-token}
</subjectCredential>
<tokens>
<token type="credential" id="0"/>
<credentialType>krb5</credentialType>
<serverPrincipal>service/ldap@stanford.edu</serverPrincipal>
</token>
</tokens>
</getTokensRequest>
<getTokensResponse>
<tokens>
<token id="0">
<tokenData>{base64}</tokenData>
</token>
</tokens>
</getTokensResponse>
The WebKDC will verify that the webkdc-proxy-token was granted to the same server specified inside of the webkdc-service-token.
All encrypted-tokens have the following general encoding:
{key-hint}{nonce}{hmac}{token-attributes}{padding}
Everything except {key-hint} is AES-encrypted.
key-hint
is UNIX UTC time stored in network byte order, and
is four bytes long. It does not get encrypted, and is only used as a *hint*
for the server
to determine which key to use to decrypt the token. It should not be used
for any other purpose as its value is not protected from modification.
nonce
is 16 random bytes, and gets encrypted with the rest of the data
in the token. It is used to ensure that two tokens with the same data
and same encryption key don't encrypt to the same value.
hmac
is the sha1 hmac of the actual data (name/value pairs),
including the padding. The key used with HMAC is the AES private-key.
Note, a better solution would be to use a different key, but that requires
have two keys or using a key-derivation function to derive the HMAC
key from the AES key. One approach would be to use a key-derivation function
like TLS uses.
token-attributes
consists of a sequence of name=value pairs,
separated by a ';' character. names are not allowed to contain
an "=" or a ";", and values MAY contain binary data, but MUST
escape any ";"'s in the data with an extra ";".
For example, if we had the following names and values:
a=1 msg=hello;there bin={binarydata} b=2
They would get encoded as:
a=1;msg=hello;;there;bin={binarydata};b=2;
padding is any additional padding of the data to make the length a multiple of 16 bytes for AES encryption. Note, there is always padding present. If the length is already a multiple of 16, then 16 bytes of padding will be added. The value of each padding byte will be equal to the length of the padding. For example, if the padding length is 7, then each byte will be equal to 0x07.
Tokens get base64 encoded before being used as a cookie, query parameter, or within XML data.
The following is the list of assigned token attributes. All attributes used within tokens are listed in this table.
All time values are stored in network byte order, and are the number of seconds since 00:00:00 UTC, January 1, 1970.
Name | Encoding | Description |
---|---|---|
as | binary | The app-token that is optionally included within a request-token that will get returned along with the response to the request-token. |
cmd | string | name of XML command being executed (i.e., getTokensRequest) |
crd | binary | credential data (i.e., an encoded krb5 service ticket) |
crs | string | credential server princpal |
crt | string | credential type (krb4, krb5) |
ct | binary time | creation time of the token. For tokens used to exchange messages between servers (request, error, id, proxy, credential) , this value is used to ensure that the request is "fresh". For example, tokens of this type with a ct older then 5 minutes will get flagged by the server (WAS or WebKDC) as being "stale". |
ec | string | error code from WebKDC. FIXME: need to document the valid error codes, they will be the same as the error codes returned in XML messages. |
em | string | error message from WebKDC. Should only be used for logging and/or debugging, since it not localized or in a format meant for end-user consumption. |
et | binary time | expiration time of the token |
k | binary | AES session key. |
lt | binary time | last-used time. If this attribute is set in an app-token, then it will be periodically updated as the token is used. |
p | string | user's password |
pd | binary | proxy data (i.e., an encoded krb5 tgt) |
ps | string | proxy subject, the subject from the service-token used when the proxy-token was granted. |
pt | string | proxy type (krb4/krb5) |
ro | string | comma-separated list of request options: lc = return the app an error code if login is canceled, fa = forced authentication (app is requesting "live" authentication) |
rtt | string | requested token type: id = id-token, proxy = proxy-token |
ru | string | return URL. The url to return the user to after authenticating with the WebKDC |
s | string | authenticated subject. In service-tokens this is the server that authenticated to get the service-token, in all other tokens it is the user that authenticated. Server subjects have the form "type:identifier". Currently, the only defined type is "krb5", and the identifier is the krb5 principal (i.e., krb5:host/lichen.stanford.edu@stanford.edu). |
sa | string | subject authenticator type (krb5, webkdc) |
sad | binary | subject authenticator data. For sa of type krb5 this is a krb5_mk_req using the same krb5 principal as the service-token's subject |
t | string | token type: webkdc-service, webkdc-proxy, req, error, id, proxy, cred, app. Used by a server to ensure that a token is being used for the correct purpose. |
wt | binary | webkdc-{proxy,service}-token (the webkdc tokens inside another token) |
u | string | user's username |
The following sections describe which attributes are include with which tokens.
webkdc-service-tokens are used by WAS servers to communicate with the WebKDC. They get returned from WebKDC after an entity authenticates with the WebKDC using the XML-interface while requesting a service-token.
t=webkdc-service
k={session-key}
s=krb5:{requesting-servers-k5-principal}
ct={creation-time}
et={expiration-time}
All attributes are AES-encrypted in WebKDC's private key. The server that initially requested the token would also have received {session-key} and {expiration-time} out-of-band from the token itself and stored them for the duration of the token.
t=webkdc-proxy
ps={subject-from-webkdc-service-token-used-to-get-proxy-ticket}
pt=krb5|krb4|...
s={username}
pd={proxy-data}
ct={creation-date}
et={expiration-date}
All attributes are AES-encrypted in the WebKDC's private key.
When a webkdc-proxy-token is used, the WebKDC checks that the subject in the service-token making the request is authorized to used the webkdc-proxy-token granted to the ps subject.
The first form is used with the requestTokenRequest command:
t=req
ct={creation-time}
[as={binary-app-token-used-for-state}]
ru={return-redirect-url}
[ro=fa,lc]
rtt=id|proxy
# for rt=id
sa=krb5|webkdc
# for rt=proxy
pt=krb5|krb4
The second form is used with the getTokensRequest command:
t=req
ct={creation-time}
cmd={xml-command-we-are-going-to-execute}
All attributes are AES-encrypted in the webkdc-service-token session-key.
The value of ct
is used to prevent replay attacks. Values older then
a certain time (probably 5 minutes by default) should be rejected as
a replay.
cmd
indicates which XML command we are invoking
(i.e., getTokensRequest). The WebKDC will compare this command
against the name of the command in the XML.
t=error
ct={creation-time}
ec={error-code}]
em={error-message}]
All attributes are AES-encrypted in the webkdc-service-token session-key
The value of ct
is used to prevent replay attacks. Values older then
a certain time (probably 5 minutes by default) should be rejected as
a replay.
t=id
sa=krb5|webkdc
# for sa=webkdc
s={username}
# for sa=krb5
sad={result-of-krb5-mk-req-for-webauth/hostname}
ct={creation-time}
et={expiration-time}
All attributes are AES-encrypted in the webkdc-service-token session-key
If "at" is krb5, then "s" (subject) is the result of a call to krb5_mk_req for the webauth/WAS service using the user's tgt.
If "at" is webkdc, then we are trusting the webkdc and "s" already contains the users's principal name.
The value of "ct" is used to prevent replay attacks. Values older then a certain time (probably 5 minutes by default) should be rejected as a replay, as id-tokens are only used once and re-written into an app-token.
The value of "et" is used to let the application know how long the subject of the id-token should be considered valid for. The value for "et" is the expiration time of the proxy-token used to create it.
t=proxy
pt=krb5|krb4|...
s={username}
wt={webkdc-proxy-token}
ct={creation-time}
et={expiration-time}
All attributes are AES-encrypted in the webkdc-service-token session-key
The value of "ct" is used to prevent replay attacks. Values older then a certain time (probably 5 minutes by default) should be rejected as a replay, as proxy-tokens are only used once and re-written into an app-token.
wt
is the webkdc-proxy-token (in binary form) that
was returned as the result of the request.
t=cred
crs={server-principal}
crt=krb5|krb4|...
s={username}
cd={credential-data}
ct={creation-date}
et={expiration-date}
All attributes are AES-encrypted in the in a webkdc-service-token session-key
t=login
ct={creation-time}
p={password}
u={username}
All attributes are AES-encrypted in the WebKDC's private key.
t=app
et={expiration-time}
[ct={creation-time}]
[s={username}]
[k=session-key]
[lt={last-use-time}]
All attributes are AES-encrypted in the WAS's private key.
app-tokens are created by mod_webauth on first receipt of an id-token. After the id-token is verified, it gets converted into an app-token.
last-use-time is only included if the webauth module is configured to keep track of it.
session-key is only present when an app-token is being used as the application-state inside of a request-token.
The tokens that get used in cookies are webkdc-proxy-tokens, proxy-tokens, app-tokens, and cred-tokens. The following naming convention will be used to name cookies.
NOTE: proxy-tokens and cred-tokens get decrypted using a session key, but will get re-encrypted using the WAS private key before getting stored in a cookie.
app-token cookies will have the name:
webauth_at
webkdc-proxy-token cookies have the following naming convention:
webauth_wpt_{proxy-type}
Where proxy-type is krb4 or krb5 depending on the type of the proxy-token.
proxy-tokens will have following naming convention:
webauth_pt_{proxy-type}
Where proxy-type is krb4 or krb5 depending on the type of the proxy-token.
cred-tokens will have the following naming convention:
webauth_ct_{cred-type}_{service-name}
where cred-type is krb4 or krb5 depending on the type of the cred-token. service-name will be the krb4 or krb5 service name, potentially with special characters escaped. XXX: need to compare valid characters in a krb4 and krb5 service name against valid characters in a cookie name.
7. Apache Directives
FIXME: Insert link to mod_webauth documentation
Date | Version | Author | Changes |
---|---|---|---|
10/02/2002 | 0.1 | schemers |
|
10/04/2002 | 0.2 | schemers |
|
10/07/2002 | 0.3 | schemers |
|
10/26/2002 | 0.4 | schemers |
|
10/30/2002 | 0.5 | schemers |
|
11/01/2002 | 0.6 | schemers |
|
11/03/2002 | 0.61 | schemers |
|
11/05/2002 | 0.7 | schemers |
|
11/07/2002 | 0.8 | schemers |
|
11/08/2002 | 0.85 | schemers |
|
11/13/2002 | 0.90 | schemers |
|
11/14/2002 | 0.91 | schemers |
|
12/04/2002 | 0.99 | schemers |
|
12/06/2002 | 1.00 | schemers |
|
12/12/2002 | 1.01 | schemers |
|
1/14/2003 | 1.02 | schemers |
|
1/20/2003 | 1.03 | schemers |
|
1/29/2003 | 1.04 | schemers |
|
7/24/2003 | 1.05 | schemers |
|