moriyoshi / cyrus-sasl-xoauth2

XOAUTH2 mechanism plugin for cyrus-sasl
MIT License
77 stars 14 forks source link

Read access tokens from the backend server #4

Open moriyoshi opened 4 years ago

moriyoshi commented 4 years ago

Heads up: this is an experimental feature and may still contain serious vulnerability, and the specification is also subject to change.

Summary

SASL_XOAUTH2_CLIENT_TOKEN_CONV environment variable

It can take a string of the following form:

PROTOCOL:HOST
PROTOCOL:PATH
PROTOCOL:HOST:PORT

ex.
tcp:localhost
tcp:localhost:65321
tcp:[::1]
tcp:[::1]:65321
unix:/tmp/server.sock

Communication Protocol

The communication is done in the following phases:

Handshake Phase

  1. Client sends a Signature and its highest available protocol version, which are concatenated, to Server.

    The Signature is a 4 octet string, %x81 %x9d %x74 %x13. The version is a 32-bit big-endian unsigned integer.

    client_hello   = signature client_version
    signature      =  %x81 %x9d %x74 %x13
    client_version = <big-endian 32-bit unsigned integer>
    
    +----+----+----+----+----+----+----+----+
    |   0|   1|   2|   3|   4|   5|   6|   7|
    +----+----+----+----+----+----+----+----+
    |0x81|0x9d|0x74|0x13| CV3| CV2| CV1| CV0|
    +----+----+----+----+----+----+----+----+
  2. Server verifies the Signature and must terminate the session if it doesn't correspond to the string. Otherwise, it responds to Client with a Signature and the protocol version which will be used in further communication.

    The Signature is a 4 octet string, %x81 %x9d %x74 %x13 (same as the above). The version is a 32-bit big-endian unsigned integer. If Server has backward compatibility with Client's protocol, it is advised that it return the same protocol version as Client.

    server_hello   = signature server_version
    server_version = <32-bit big-endian unsigned integer>
  3. Upon reception of the response from Server, Client must terminate the session if the signature doesn't match, and may do so if the Server's protocol version doesn't meet its version.

  4. Client and Server step to Query Phase.

Query Phase

  1. Client sends a Packet with the following content:

    packet               = packet_length packet_content
    packet_length        = <32-bit big-endian unsigned integer>
    
    query_packet         = query_packet_length query_packet_content 
    query_packet_content = "authid" %x00 authid
    authid               = *%x00-ff

    A Packet starts with a 32-bit big-endian unsigned integer that stores the length of the packet content (length octets excluded) and is immediately followed by the packet content.

  2. Server receives the query Packet and responds with the access token that corresponds to the authentication ID contained in the query.

    resp_packet          = resp_packet_length resp_packet_content 
    resp_packet_content  = access_token
  3. Client may repeat queries.