- simplified ASPNET Security-like libraries.
- rewritten from scratch ASPNET Security libraries.
- "light" functional-style libraries [90% OOP-free].
- Authentication.Cookies.
- Authentication.Facebook.
- Authentication.Google.
- Authentication.Twitter.
- Authentication.BearerToken.
- Authentication.OAuth2.
- Authentication.OpenIdConnect.
- Authorization.
- DataProtection.
- security services [authentication and authorization services] represent the mechanism backbone.
- security services [high-level functions] act as security behaviour controllers and represent public API.
- security libraries were written following some of FP principles [pure functions, high-order functions, immutability, data/behaviour separation, static methods/functions as first-class citiziens, result pattern].
- DI is used as thin layer usually over functional security services [eg. SignInCookie have 2 implementations with/without DI services]. DI services implementations are registred as usual with specific method extensions [eg. AddCookiesServices, AddFacebookServices].
- security mechanism is based on security services [authentication scheme free-mechanism]:
- authentication middleware receive authentication service as param [UseAuthentication extension].
- authorization middleware receive challenge and forbid services as params [UseAuthorization extension].
- oauth callback endpoints receive signin service as param [eg. MapFacebook].
- authentication libraries implement specific authentication services [eg. AuthenticateCookie, SignInCookie, ChallengeGoogle, AuthenticateFacebook].
- authorization library implement authorization services [eg. Authorize].
- high-level functions usually use declarative style [eg. SignInCookie].
- usually impure functions [with side-effects].
- built on top of low-level and intermediate-level functions.
- intermediate-level functions use imperative/declarative style [eg. SetAuthorizationParams].
- low-level functions usually use imperative style and are one-liners [eg. IsSecuredCookie].
- usually pure [without side effects] or semi-pure functions [side effects on parameters].
- high-intermediate-low-level hierarchy design I named it lego principle. It could be seen also as a functions pyramid having at the base low-level functions.
- no else strategy [0 (zero) else branches].
- there are 2 different security processes: local authentication and remote authentication.
- local authentication process [cookie]:
- each request [when use authentication middlware] call authentication func [eg. AuthenticateCookie]. Based on authentication result the middleware set HttpContext.User prop.
- then each request [when use authorization middlware] call authorization func [eg. Authorize]. Based on authorization policies result is decided if the request is allowed, unauthenticated/challenged or unauthorized/forbidden.
- signin/signout funcs are used on specific endpoints/controller actions implememted by devs.
- remote authentication process [OAuth2 protocol]:
- when called, the challenge endpoint [eg. registered with MapFacebook] build and send an authorization request to authorization server.
- after processing the authorization request the authorization server redirect response to callback endpoint [eg. registered with MapFacebook]. That endpoint receive authorization server response and call callback func [eg. CallbackFacebook, CallbackOAuth]. The callback func has 2 steps:
- authentication: AuthenticateOAuth oauth authentication func has 3 substeps:
- PostAuthorization - validate the authorization code and the request from the authorization server [local].
- ExchangeCodeForTokens - exchange with the authorization server the authorization code for the access [and refresh] tokens [remote].
- AccessUserInfo - using access token gets from the authorization server the user informations [remote].
- The authentication step transform user informations received from authorization server into security claims, add them to the claims identity, create an authentication ticket and return the AuthenticationResult.
- signin: after oauth authentication step when authentication succedded then the signin func is called [eg. *SiginInCookie^, SignInBearerToken]. Signin func is set on oauth endpoints registration.
- authentication: AuthenticateOAuth oauth authentication func has 3 substeps:
- after callback redirection next requests will use local authentication process.
- completely rewritten authentication mechanism.
- partially rewritten authorization mechamism [keeping compatibility with ASPNET authorization policies mechanism].
- cookie authentication services surgically implement session-based cookies feature [using IsSessionBasedCookie func]. Authenticating, signingin and signingout services are completely independent each other [no dependencies on HttpContext features]. AuthenticationSessionCookie, SignInSessionCookie and SignOutSessionCookie session-based cookies services are completely isolated from non-session based versions.
- authentication options implementation contains only data [eg. CookieAuthenticationOptions]. Cookie authentication services [non DI-based ones] receive all dependencies as parameters.
- Microsoft ASPNET authentication options implementation contains data and behaviour/services [eg. SessionStore, TicketDataFormat, SystemClock for CookieAuthenticationOptions]. This design have some advantages comparing with my implementation allowing options:
- to have different services from those registered on DI.
- to encapsulate and carry on those services through the authentication process [reducing the number of parameters so].
- AuthenticateOAuth oauth authentication func use template method design pattern allowing oauth libraries to override/decorate when neccessary postAuthenticate, exchangeCodeForTokens or accessUserInfo authentication substeps [eg. AuthenticateTwitter, AuthenticateFacebook].
- redirecting remarks:
- ChallengeOAuth and ChallengeOidc funcs redirect to authorization server [ChallengeOidc could use form instead of redirection].
- CallbackOAuth and CallbackOidc funcs redirect to original url or when callback authentication error to AccessDeniedPath or ErrorPath authentication options props depending of error type.
- SigninCookie, SignOutCookie, Challenge*, Forbid* etc. no redirections [webapi oriented functionality]. when redirections are neccessary those funcs could be decorated and redirected to AuthenticationProperties.RedirectUri or to AuthenticationOptions.ReturnUrlParameter query parameter.
- cookies remarks:
- AuthenticationCookieOptions.ExpiresAfter single place to control AuthenticationTicket [cookies] persistency.
- AuthenticationCookieOptions.CookieName single place to control cookies names.
- oidc remarks:
- pkce is the recommended solution regarding security for authorization code flow.
- implicit and hybrid flows not supported based on oidc best practices [even supported by oidc rfc].
- nonce is not neccessary because implicit and hybrid are only flows with required nonce parameter.
- to untangle/demystify the ASPNET authentication/authorization mechanisms and local/remote processes.
- to simplify authentication/authorization mechanisms [ASPNET schema-based free mechanism].
- to demonstrate a functional programming implementation.
- to demonstrate a practical alternative to OOP.
Method | InvocationCount | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|---|---|
FPSignin | 128 | 64.34 μs | 1.196 μs | 1.119 μs | 64.69 μs | 1.00 | 0.00 | - | - | - | 7.96 KB | 1.00 |
OOPSignin | 128 | 79.98 μs | 3.247 μs | 9.212 μs | 79.56 μs | 1.13 | 0.14 | 7.8125 | 7.8125 | 7.8125 | 116.21 KB | 14.59 |
FPSignin | 512 | 45.75 μs | 5.065 μs | 14.934 μs | 39.12 μs | 1.00 | 0.00 | 1.9531 | - | - | 7.96 KB | 1.00 |
OOPSignin | 512 | 97.08 μs | 7.432 μs | 21.679 μs | 95.52 μs | 2.41 | 1.12 | 9.7656 | 9.7656 | 9.7656 | 445.7 KB | 56.01 |
FPSignin | 1024 | 28.83 μs | 2.009 μs | 5.533 μs | 26.26 μs | 1.00 | 0.00 | 1.9531 | - | - | 7.95 KB | 1.00 |
OOPSignin | 1024 | 186.15 μs | 26.776 μs | 78.949 μs | 211.04 μs | 6.32 | 3.02 | 14.6484 | 13.6719 | 13.6719 | 915.64 KB | 115.12 |
- for InvocationCount > 2048 OOP benchmark start running extremely slow.