# Copyright © 2020 Gregor Reitzenstein # Licensed under the MIT License: # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @0x81ac94a588025602; using Rust = import "rust.capnp"; $Rust.parentModule("schema"); using CSharp = import "csharp.capnp"; $CSharp.namespace("FabAccessAPI.Schema"); using Api = import "api.capnp"; interface Authentication { mechanisms @0 () -> ( mechs :List(Text) ); # Get the list of mechanisms supported by the server start @1 ( request :Request ) -> ( response :Response ); # Initiate an authentication exchange # NOTE: Calling start() after an authentication exchange has already # finished is undefined behaviour. If you want to double-authenticate call # auth() from connection.capnp again to get a fresh capability you can use. # This may however return NULL if you are not allowed to authenticate twice. step @2 ( response :Data ) -> ( response :Response ); # Respond to a challenge with more data # NOTE: As with start() calling this after having received an outcome is # undefined behaviour. abort @3 () -> (); # Abort the current exchange. This may be sent by both client and server # at any point during the exchange. It MUST not be sent by a server # after sending an outcome or by a client after receiving an outcome. # A server receiving an abort after sending an outcome but before # receiving any other message MUST respect the abort. whoami @4 () -> ( you :Api.User, dummy :UInt8 = 0 ); # Returns NULL if not authenticated and an User object if authenticated. } struct Request { mechanism @0 :Text; # The SASL mechanism name. initialResponse :union { # A client may send some intial data when requesting an auth exchange. # According to RFC4422 section 4.3a an implementation MUST be able to # distinguish between an empty initial reponse and no initial response. none @1 :Void; # No initial reponse is being sent. # The lowest numbered field in an union is the default value in Cap'n # Proto. initial @2 :Data; # A response may be any sequence of octets, including zero-length # sequences and zero-valued octets. } } struct Response { enum Result { # Result code of the outcome successful @0; badMechanism @1; # The server does not support this mechanism in this context. unwilling @2; # Generic "I'm sorry dave, I can't do that" response. MAY be set for any # reason, all reasons or no reason at all. # A server SHOULD set the `action` and `helpText` fields as appropiate. # This code SHOULD only be sent if no other value is more fitting. invalidCredentials @3; # The exchange was valid, but the provided credentials are invalid. This # may mean that the authcid is not known to the server or that the # password/certificate/key/etc. is not correct. unauthorized @4; # The given authcid is not authorized to act as the requested authzid. # This MAY also be returned for the cases `authzid == NULL` or # `authzid == authcid`, for example because login is disabled for that # authcid. malformedAuthZid @5; # The provided authzid is malformed in some way. failed @6; # A generic failed result. A server sending this result MUST set the # `action` field to indicate whether this is a temporary or permanent # failure and SHOULD set `helpText` to a human-readable error message. } enum Action { # In case of a unsuccessful outcome, how should a client proceed? unset @0; # Not a unsuccessful outcome, or the server doesn't know either. # Also, the default value retry @1; # A client should just try again, potentially after prompting the user # to enter their credentials again. wait @2; # The client should wait and try again later. This MAY mean that # whatever failure happened was temporary or the server is applying # rate-limiting to the connection. permanent @3; # The issue appears to the server as being permanent. Another try is # very likely to return the exact same result. In most cases the user # should notify the responsible system administrator. } union { challence @0 :Data; outcome :group { result @1 :Result; # Result code action @2 :Action; # Hints for the client how to proceed in case of an error helpText @3 :Text; # Human-readable further information in case of an error additionalData :union { # Additional data that may be sent by the server to the client after a # successful authentication exchange. none @4 :Void; # No additional data is being sent. This MUST be set on unsuccessful # outcomes. additional @5 :Data; # Additional data may be any sequence of octets, including zero-length # sequences and zero-value octets. } } } }