FTN3: FutoIn Security Concept
Version: 0.1
Date: 2014-06-03
Copyright: 2014 FutoIn Project (http://futoin.org)
Authors: Andrey Galkin

CHANGES

Warning

!!! THIS ONE IS HEAVILY OUTDATED. IT NEEDS TO BE REWRITTEN AND REDESIGNED !!!

This document is not actually a specification, but more an overview as it requires a LOT of polishing first.

Unfortunately. At the moment of writing this specification, the author knows quite little about Security to judge the strength of proposed algorithms. Every single part of that requires deep analysis of experts.

1. Intro

Security concept is required to build a unified authentication and authorization model across security domains with separate control in open environment like internet.

There is no global trusted party is allowed. Chain of trust must be fully distributed.

2. Functional description

2.1. Security Contexts

There are three major security context types:

Each Service and each Client must trust only one AuthService. If they trust different AuthServices then it is responsibility of AuthService to establish communication to another AuthService. In such case, Client is called foreign AuthService user or simply foreign user.

2.2. Service to Service interaction (and Service to AuthService in particular)

This is generic mechanism to establish interaction between any two services, where one Service acts as shared secret MasterService.

MasterService is always the Server peer in initial interaction.

AuthService always acts as MasterService.

2.2.1. Establishing interaction

2.2.2. Shared secret

2.2.3. Unregistration from MasterService

Under some communication patterns, a persistent shared secret exchange is not required. It must be possible to unregister from MasterService.

2.2.4. Example

    Service                     MasterService
       |                              |
       |-------- register ----------> |
       | <------- newSharedKey -------|
                    ...
       | <------- newSharedKey -------|
                    ...
       |                              |
       |------- unRegister ---------> |
       |                              |

2.3. Stateful user authentication

This is default method to be used for most cases.

2.3.1. Security Levels

In some cases, Client may be allowed to get read-only information without deep verification, but it becomes really important for all modification type of requests.

2.3.2. Validation Constraints

2.3.3. Example

    Client                     Service                      AuthService
       |                          |                              |
       |------ getSignIn -------> |                              |
       | <--- Redirect signIn ----|                              |
       |------------------ signIn -----------------------------> |
       | <------------------ SignIn page/form -------------------|
       | [----------------- authBySecret---------------------->] |
       |----------- completeSignIn or cancelSignIn ------------> |
       |-------- complete ------> |                              |
       |                          |---------- validate --------> |
       |                          | <-- validation constraints --|
       |                          |                              |

2.4. Stateless user authentication

This authentication method is designed for stateless API calls with limited authorization capabilities as it is not always feasible to establish secure credentials management and/or implement a statefull client.

Credentials information is sent along-side API request.

2.4.1. Example

    Client                     Service                      AuthService
       |                          |                              |
       |------ API request -----> |                              |
       |                          |---- validateBySecret ------> |
       |                          | <-- validation constraints --|
       | <---- API response ------|                              |
       |                          |                              |

2.5. User authentication methods

Note: Service or AuthService is determined based on Stateless or Stateful authentication type

Client password is stored in hash with salt.

2.5.1. Auth by clear text credentials

Note 1: This mechanism is allowed ONLY for Stateless user authentication.

Note 2: This mechanism is allowed only for SafeOps and lower security level

Note 3: Password must be unique for every Service configured for Client

2.5.2. Auth by Challenge-Response Authentication

2.5.3. Auth by X509 certificate through Service

2.5.4. Auth by public key through Service

2.5.5. Auth by IPv4/IPv6 address

2.6. Multi-method user authentication

There must be one or more sets of authentication methods. In every set, there can be one or more authentication method.

Authentication succeeds only if all methods of any set pass.

2.7. HMAC generation

See HMAC for details

2.7.1 Rules of HMAC generation for payload

2.8. Client information exposed from AuthService to Service

Service can inform AuthService which Client information fields must be approved by Client to be exposed to Service. Client authentication cannot succeed unless Client approves fields being exposed to specific Service. This functionality is available only for Stateful authentication.

Note: AuthService must store list of approved fields per Client-Service pair. Service must re-send Client for authentication, if more fields need to be approved

2.8.1. List of standard field identifiers

2.9. Client authentication invalidation event

2.10. Foreign user authentication

If Client is foreign user then AuthService acts as Service to user "domestic" AuthService, performing all communication transparently to original Service and Client.

For security reasons, only authentication requests from pre-approved Service list should be forwarded to another AuthService.

3. Defense system integration

Security is common responsibility. Every node of the system must be a defense barrier for both attacks and simple misconfiguration.

Typically, more farther node from actual attacker should have a dynamic failure rate limit to avoid a closer node being banned, leading to Denial of Service of specific functionality.

Each service must detect attacking Clients/Services and deny access before security limit is triggered on another host.

Note: all hit or approaching limits must be reported to administration for actions to be taken

Any error, which never happens by race condition, mistake, etc. must immediately trigger defense system action Example: session token validation by other Service.

3.1. Possible limit types

4. Detailed encryption and authentication requirements

SHA-3 was desired as a start, but SHA-2 is more widespread at the moment. So, SHA-2 is to be used until SHA-3 is penetrated into most technologies.

SHA-384, SHA-512 or its truncated version SHA-512/224, SHA-512/256 is to be used at the moment. Dependant peer must deduce actual hash function based on hash length.

AES-256 is to be used as encryption cipher. Therefore minimal shared secret length is 256-bit. Longer keys should be truncated.

4.1. Message "sec" field sub-schema for HMAC

Schema: futoin-sec-hmac

    {
        "title" : "FutoIn 'sec' field - HMAC",
        "type" : "object",
        "additionalProperties" : false,
        "required" : [ "ksn", "hmac" ],
        "properties" : {
            "ki" : {
                "type" : "string",
                "description" : "Base shared secret ID"
            },
            "di" : {
                "type" : "string",
                "description" : "Derived key sequence ID"
            },
            "hmac" : {
                "type" : "string",
                "description" : "Base64 encoded HMAC"
            }
        }
    }

4.2. Message "sec" field sub-schema for Stateless authentication

Schema: futoin-sec-credentials

    {
        "title" : "FutoIn 'sec' field - Credentials",
        "type" : "object",
        "additionalProperties" : false,
        "required" : [ "user" ],
        "properties" : {
            "user" : {
                "type" : "string",
                "description" : "Unique user identification"
            },
            "secret" : {
                "type" : "string",
                "description" : "Any type of secret, typically password"
            }
        }
    }

5. Access Control Service

In many cases, there is a fixed number of object types, like users, posts, files, etc. And there is a variable size of objects per type, many users, posts and files. Every object can have Create/Read/Update/Delete action.

We can see a hierarchy here: Service -> Object Types -> Individual Objects -> Individual Object Action.

Another type of hierarchy can be: Service -> Interface -> Function.

In all cases it is possible to unify access control system to operate on neutral tree-like structure of identifiers. On low level, Client access is controlled on specific end-object+action. The details of how access is granted (e.g. roles, individual permissions, ownership, etc.) are AccessControlService implementation details. However, access can be granted by parent node and/or access control tree mask, where some of parent nodes can be "any".

Doing an API call for every action may produce a significant overhead. It is important to design effective caching mechanism with stable invalidation for security reasons.

5.1. Access Control descriptor

There must be a common notation to identify object of checked control. In API, the access notation is an ordered array, where the first item is the top most in scope.

Descriptor scope is specific to context. In Service context, scope is the Service. In Access Control Service, the scope is a common set of all Services registered to the system (meaning the first element is Service identifier).

Example: ["root_node", "object_type", "action"]

In some cases, wildcard is desired for some items. Example: grant update access to all users. Wildcard is marked as null value in place of item in the descriptor array.

Example: ["root_node", null, "action"]

For human readable purpose, the same descriptor can be written in string form, each item being separated by dot "." and wildcard null being replaced by star "*".

Example: "root.object_type.action", "root..action"*

5.2. Access Control check

5.3. Example

    Client                     Service                      AccessControlService
       |                          |                              |
       |-------- request -------> |                              |
       |                          |--------- checkAccess ------> |
       |                          | <-- validation constraints --|
       | <------ response --------|                              |
       |                          |                              |

6. Defense Systems

Any open system requires effective reaction to errors generated by misconfiguration and intentional attacks. It is also required to impose limits on utilization of resources for normal operation.

There are no requirements on how defense system must behave to identify possible attacks and misconfiguration, and how to react to them. It is like a fraud detection system - a full time job type of thing.

However, this specification defines a universal interface for system audit and reaction.

6.1. Example

7. Interface definitions

7.1. MasterService provider

7.2. MasterService consumer

    {
        "iface" : "futoin.master.consumer",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "newSharedKey" : {
                "params" : {
                    "key_id" :  {
                        "type" : "string",
                        "desc" : "Shared secret ID"
                    },
                    "enc_key" : {
                        "type" : "string",
                        "desc" : "Key, encrypted with the same key as used for HMAC"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                }
            }
        },
        "requires" : [
            "SecureChannel"
        ],
        "desc" : "MasterService Provider interface"
    }

7.3. AuthService backend provider (Service interface)

    {
        "iface" : "futoin.auth.backend",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "getClientInfo" : {
                "params" : {
                    "session" : {
                        "type" : "string",
                        "desc" : "Session token from futoin.auth.consumer.complete.ssn"
                    }
                },
                "result" : {
                    "info" : {
                        "type" : "map",
                        "desc" : "Map of Private Info fields, allowed by Client to be sent"
                    }
                },
                "throws" : [
                    "InvalidSessionID"
                ]
            },
            "validate" : {
                "params" : {
                    "session" : {
                        "type" : "string",
                        "desc" : "Session token from futoin.auth.consumer.complete.essn"
                    }
                },
                "result" : {
                    "constraints" : {
                        "type" : "array",
                        "desc" : "Array of object sets of constraints"
                    }
                },
                "throws" : [
                    "InvalidSessionID"
                ]
            },
            "validateBySecret" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "secret" : {
                        "type" : "string",
                        "desc" : "Client secret"
                    }
                },
                "result" : {
                    "constraints" : {
                        "type" : "array",
                        "desc" : "Array of object sets of constraints"
                    }
                },
                "throws" : [
                    "InvalidClientID",
                    "InvalidSecret",
                    "Blocked"
                ],
                "desc" : "Authorize by ID/secret pair"
            }
        },
        "requires" : [
            "SecureChannel"
        ],
        "desc" : "AuthService Backend Provider interface"
    }

7.4. AuthService frontend provider (Client interface)

    {
        "iface" : "futoin.auth.frontend",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "signIn" : {
                "params" : {
                    "lvl" : {
                        "type" : "string",
                        "desc" : "Required Security Level"
                    },
                    "pf" : {
                        "type" : "array",
                        "desc" : "List of private field access to request"
                    },
                    "tkn" : {
                        "type" : "string",
                        "desc" : "Requesting Service provided client token"
                    }
                },
                "desc" : "Special handling. Service and its callback must be determined from sec.ki parameter. Client is 'transport'"
            },
            "authBySecret" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "secret" : {
                        "type" : "string",
                        "desc" : "Client secret"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                },
                "throws" : [
                    "InvalidClientID",
                    "InvalidSecret",
                    "Blocked"
                ],
                "desc" : "Authorize by ID/secret pair"
            },
            "completeSignIn" : {
                "result" : {
                    "redirect" : {
                        "type" : "string",
                        "desc" : "Redirect URL to return to requesting Service"
                    }
                }
            },
            "cancelSignIn" : {
                "result" : {
                    "redirect" : {
                        "type" : "string",
                        "desc" : "Redirect URL to return to requesting Service"
                    }
                }
            }
        },
        "requires" : [
            "AllowAnonymous",
            "SecureChannel"
        ],
        "desc" : "AuthService Backend Provider interface"
    }

7.5. AuthConsumer (Service interface)

    {
        "iface" : "futoin.auth.consumer",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "complete" : {
                "params" : {
                    "essn" : {
                        "type" : "string",
                        "desc" : "Encrypted session token ID"
                    },
                    "ttl" : {
                        "type" : "string",
                        "desc" : "Time-to-Live for Client session"
                    }
                }
            },
            "getSignIn" : {
                "result" : {
                    "url" : {
                        "type" : "string",
                        "desc" : "AuthService redirection URL"
                    }
                }
            },
            "invalidate" : {
                "params" : {
                    "essn" : {
                        "type" : "string",
                        "desc" : "Encrypted session token ID"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                },
                "desc" : "Invalidate session and force re-check on next user activity or earlier"
            }
        },
        "requires" : [
            "AllowAnonymous"
        ],
        "desc" : "AuthService Backend Provider interface"
    }

7.6. AccessControl provider

    {
        "iface" : "futoin.acl.provider",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "checkAccess" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor"
                    }
                },
                "result" : {
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor"
                    },
                    "ttl" : {
                        "type" : "string",
                        "desc" : "Time-to-Live for client descriptor cache"
                    },
                    "auth_level" : {
                        "type" : "string",
                        "desc" : "Required Security Level"
                    }
                },
                "throws" : [
                    "Forbidden"
                ],
                "desc" : "Check access to calling Service"
            },
            "grantAccess" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                },
                "desc" : "Grant access to specific descriptor"
            },
            "requestAccess" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                },
                "desc" : "Request access for specific client to be later approved by Admin"
            },
            "revokeAccess" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                },
                "desc" : "Revoke access to specific descriptor"
            }
        },
        "requires" : [
            "SecureChannel"
        ],
        "desc" : "AuthService Backend Provider interface"
    }

7.7. AccessControl consumer

    {
        "iface" : "futoin.acl.consumer",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "invalidate" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor"
                    }
                },
                "result" : {
                    "ok" : {
                        "type" : "boolean",
                        "desc" : "Always true, if no exception"
                    }
                },
                "desc" : "Invalidate cached Client's access control descriptor"
            },
            "getDescriptors" : {
                "params" : {
                    "acd" : {
                        "type" : "array",
                        "desc" : "Access control descriptor. If not empty, skip not matching and not sub-tree"
                    },
                    "locale" : {
                        "type" : "string",
                        "desc" : "Get locale name for translations"
                    }
                },
                "desc" : "Get futoin-acl-tree file"
            }
        },
        "requires" : [
            "SecureChannel"
        ],
        "desc" : "AuthService Backend Provider interface"
    }

Schema: futoin-acl-tree

    {
        "title" : "FutoIn ACL tree",
        "type" : "object",
        "additionalProperties" : false,
        "required" : [ "auth_level" ],
        "properties" : {
            "auth_level" : {
                "type" : "string",
                "description" : "Required Auth Level"
            },
            "print_name" : {
                "type" : "string",
                "description" : "Print name"
            },
            "desc" : {
                "type" : "string",
                "description" : "Description in MarkDown format"
            },
            "children" : {
                "type" : "object",
                "description" : "Recursive structure"
            }
        }
    }

7.8. DefenseService interface

    {
        "iface" : "futoin.defense.provider",
        "version" : "{ver}",
        "ftn3rev" : "1.4",
        "funcs" : {
            "onCall" : {
                "params" : {
                    "client_id" : {
                        "type" : "string",
                        "desc" : "Unique Client ID"
                    },
                    "client_addr" : {
                        "type" : "string",
                        "desc" : "IPv4:addr, IPv6:addr or other-type:addr, optionally followed by :port or :path"
                    },
                    "request" : {
                        "type" : "map",
                        "desc" : "Original request data"
                    }
                },
                "result" : {
                    "act" : {
                        "type" : "string",
                        "desc" : "one of: pass, drop, reject, reauth, delay"
                    },
                    "delay" : {
                        "type" : "number",
                        "desc" : "delay response (processing for 'delay') for specific absolute time in microseconds since request was made for _any_ action"
                    },
                    "refid" : {
                        "type" : "string",
                        "desc" : "Reference ID for onResult()"
                    }
                },
                "desc" : "Call before processing each client's call"
            },
            "onResult" : {
                "params" : {
                    "refid" : {
                        "type" : "string",
                        "desc" : "Reference ID for onCall()"
                    },
                    "response" : {
                        "type" : "map",
                        "desc" : "Original response data"
                    }
                },
                "desc" : "Call after processing each client's call"
            },
            "onFail" : {
                "params" : {
                    "refid" : {
                        "type" : "string",
                        "desc" : "Reference ID for onCall()"
                    },
                    "error" : {
                        "type" : "string",
                        "desc" : "Generated error"
                    }
                },
                "result" : {
                    "delay" : {
                        "type" : "number",
                        "desc" : "delay response for specific absolute time in microseconds since request was made"
                    }
                },
                "desc" : "Call before processing each client's call"
            }
        },
        "requires" : [
            "SecureChannel"
        ],
        "desc" : "AuthService Backend Provider interface"
    }

7.9. Example: Holistic picture with all peers in scope

Yes, it may look like too much of overhead, but it is what is done in all-in-one implementation in scope of single process. It is very important to optimize communication with backend services, possibly clustering them to the same OS instance as running Service.

    Client            Service    [AuthService]   ACLService   DefenseService
       |                 |                 |          |            |
       |--- request ---> |                 |          |            |
       |                 |----------- onCall() ------------------> |
       |                 | <----- defense action ------------------|
       |                 |- valBySecret -> |          |            |
       |                 | <-- val cnstr --|          |            |
       |                 |----- checkAccess --------> |            |
       |                 | <- validation constraints -|            |
       |           [defense action]        |          |            |
       |             [process]             |          |            |
       |                 |----------- onResult() ----------------> |
       | <- response ----|                 |          |            |
       |                 |                 |          |            |

=END OF SPEC=