I have a web server than returns a WWW-Authenticate: Negotiate
HTTP header (no <value>
), which indicates the client should authenticate using Kerberos.
Then the client generates a Kerberos token as follows (the input token is empty):
gss_init_sec_context(
&minor_status, GSS_C_NO_CREDENTIAL, (gss_ctx_id_t*)context, (gss_name_t)name, GSS_KRB5_MECHANISM,
request_flags, 0, GSS_C_NO_CHANNEL_BINDINGS, (gss_buffer_desc*)input_token_x, nullptr,
(gss_buffer_desc*)output_token, &return_flags, nullptr);
This token can only be used for a single request (why?) for which the server responds with a WWW-Authenticate: Negotiate <value>
HTTP header, like:
WWW-Authenticate: Negotiate YIGZBgkqhkiG9xIBAgICAG+BiTCBhqADAgEFoQMCAQ+iejB4oAMCARKicQRv3w2k6UrZ+MQ2wnUaWFxGjiWXi/QHrcdcjlklMW7uCgYUsaLqwO6ihBIxjfSSSHxmMm6JMwbf/0xrN8gMq5D9By9/5YKIOzQWKjwm73CfkrvMAq+Ns0StFfXxkx3rFm2u0OBpuaB77TubvLsMap45
Now what should this <value>
be utilized for?
Should I run gss_init_sec_context()
with an empty input token before every web request, similar to how it's done in requests-kerberos?
It seems wrong thus... I would like to obtain a long-lived token. How is the <value>
normally utilized?
You generate the initial token for an
Authorization: Negotiate
request by callinggss_init_sec_context()
with no input token.If the server returns a 401 with
WWW-Authenticate: Negotiate <value>
, it means the negotiation has not finished yet. You callgss_init_sec_context()
again, this time passing the value as the input token parameter (after decoding). You send the resulting token with anotherAuthorization: Negotiate
request. You do it until you either getWWW-Authenticate: Negotiate
with no data attached (meaning the negotiation has failed), or some other response, normally 200 but may be anything else like 301 (meaning the authorization has succeeded).Some servers may be configured to require authentication with every request or once per connection. If the latter, the server will not send
WWW-Authenticate
with subsequent requests and you don't need to send anyAuthorization
. The server will sendPersistent-Auth: true
if so. At any rate you cannot reuse the negotiation token. You either issue a new token for every request, or do not send any tokens after the initial one if Persistent-Auth is set to true.You don't have to wait for
WWW-Authenticate: Negotiate
to generate a token. If you know that the server uses this protocol, just sendAuthorization: Negotiate <token>
right away.Now you may get another
WWW-Authenticate: Negotiate
with a token with a 200 response (or I presume other responses indicating success). This token is the server's mutual authentication token. If you get one, you should callgss_init_sec_context()
with it yet another time. Ifgss_init_sec_context()
returns a success, you are all set. Otherwise it means that the client could not authenticate the server (maybe the server was not set up correctly, or someone is trying to impersonate it).References: