From 8772e8914f93b7e0740c680b9de3fb2bf32eee4f Mon Sep 17 00:00:00 2001 From: Aaron Klish Date: Mon, 25 Feb 2019 12:11:19 -0600 Subject: [PATCH 1/4] Updated documentation on how to pass a User object to Elide --- pages/guide/03-security.md | 49 ++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/pages/guide/03-security.md b/pages/guide/03-security.md index 64551701..cfa5a2aa 100644 --- a/pages/guide/03-security.md +++ b/pages/guide/03-security.md @@ -1,5 +1,3 @@ ---- -layout: guide group: guide title: Security --- @@ -8,7 +6,7 @@ title: Security API authentication is largely a solved problem and generally outside the scope of Elide. Authorization - the act of verifying data and operation access for an _already authenticated user_ in the Elide framework involves a few core concepts: -* **User** - Each API request is associated with a user principal. The user is opaque to the Elide framework but is passed to developer-defined _check_ functions that evaluate arbitrary logic or build filter expressions. +* **User** - Each API request is associated with a user principal. The user is opaque to the Elide framework but is passed to developer-defined _check_ functions that evaluate arbitrary logic or build filter expressions. More details can be found [here](#user). * **Checks** - a function _or_ filter expression that grants or denies a user **permission** to perform a particular action. * **Permissions** - a set of annotations (read, update, delete, create, and share) that correspond to actions on the data model's entities and fields. Each **permission** is decorated with one or more checks that are evaluated when a user attempts to perform that action. @@ -127,12 +125,55 @@ Filter expression checks are most important when a security rule is tied in some ## User --------------------- -Each request is associated with a user. The user is computed by a function that you provide conforming to the interface: +Each request is associated with a user. By default the user is simply an instance of a [SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html) object. + +The `SecurityContext` is created outside the Elide framework in a [JAX-RS](https://jcp.org/en/jsr/detail?id=311) [ContainerRequestFilter](https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ContainerRequestFilter.html): + +```java + @Override + public void filter(ContainerRequestContext containerRequestContext) throws IOException { + containerRequestContext.setSecurityContext(new SecurityContext() { + + ... +``` + +This filter will typically authenticate the request and store an identifier about the user inside the new `SecurityContext`. + +Elide also supports other objects besides the `SecurityContext` as the user. You can supply any object you want by mapping the supplied +`SecurityContext` to something else. The mapping function must conform to this interface: ```java Function ``` +The JSON-API and GraphQL JAX-RS endpoints are injected with this function during initialization: + +```java + @Inject + public JsonApiEndpoint(@Named("elide") Elide elide, + @Named("elideUserExtractionFunction") DefaultOpaqueUserFunction getUser) { +``` + +```java + @Inject + public GraphQLEndpoint( + @Named("elide") Elide elide, + @Named("elideUserExtractionFunction") DefaultOpaqueUserFunction getUser) { +``` + +The Elide standalone repository overrides the default to map the user to a [Principal](https://docs.oracle.com/javase/10/docs/api/java/security/Principal.html) object instead: + +```java + /** + * The function used to extract a user from the SecurityContext. + * + * @return Function for user extraction. + */ + default DefaultOpaqueUserFunction getUserExtractionFunction() { + return SecurityContext::getUserPrincipal; + } +``` + ## Permission Annotations --------------------- The permission annotations include `ReadPermission`, `UpdatePermission`, `CreatePermission`, `DeletePermission`, and `SharePermission`. Permissions are annotations which can be applied to a model at the `package`, `entity`, or `field`-level. The most specific annotation always take precedence (`package < entity < field`). More specifically, a field annotation overrides the behavior of an entity annotation. An entity annotation overrides the behavior of a package annotation. Entity annotations can be inherited from superclasses. When no annotation is provided at any level, access is implicitly granted for `ReadPermission`, `UpdatePermission`, `CreatePermission`, and `DeletePermission` and implicitly denied for `SharePermission`. From f35f41e637abb97060cce541cabb72f50e456492 Mon Sep 17 00:00:00 2001 From: Aaron Klish Date: Mon, 25 Feb 2019 12:12:17 -0600 Subject: [PATCH 2/4] Fixed accidental deletion --- pages/guide/03-security.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/guide/03-security.md b/pages/guide/03-security.md index cfa5a2aa..c052d5d6 100644 --- a/pages/guide/03-security.md +++ b/pages/guide/03-security.md @@ -1,3 +1,5 @@ +--- +layout: guide group: guide title: Security --- From ad3a043b5f3a63ecc1a3cfb6f23b7e7c5deafed8 Mon Sep 17 00:00:00 2001 From: Aaron Klish Date: Mon, 25 Feb 2019 16:42:32 -0600 Subject: [PATCH 3/4] Clarified that the principal/security context is wrapped in a User object --- pages/guide/03-security.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/guide/03-security.md b/pages/guide/03-security.md index c052d5d6..a452de86 100644 --- a/pages/guide/03-security.md +++ b/pages/guide/03-security.md @@ -127,7 +127,7 @@ Filter expression checks are most important when a security rule is tied in some ## User --------------------- -Each request is associated with a user. By default the user is simply an instance of a [SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html) object. +Each request is associated with a user. By default the user is simply an opaque object that wraps an instance of a [SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html) object. The `SecurityContext` is created outside the Elide framework in a [JAX-RS](https://jcp.org/en/jsr/detail?id=311) [ContainerRequestFilter](https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ContainerRequestFilter.html): @@ -141,7 +141,7 @@ The `SecurityContext` is created outside the Elide framework in a [JAX-RS](https This filter will typically authenticate the request and store an identifier about the user inside the new `SecurityContext`. -Elide also supports other objects besides the `SecurityContext` as the user. You can supply any object you want by mapping the supplied +Elide also supports other objects besides the `SecurityContext` as the principal. You can supply any object you want by mapping the supplied `SecurityContext` to something else. The mapping function must conform to this interface: ```java @@ -163,7 +163,7 @@ The JSON-API and GraphQL JAX-RS endpoints are injected with this function during @Named("elideUserExtractionFunction") DefaultOpaqueUserFunction getUser) { ``` -The Elide standalone repository overrides the default to map the user to a [Principal](https://docs.oracle.com/javase/10/docs/api/java/security/Principal.html) object instead: +The Elide standalone repository overrides the default to map the `SecurityContext` to a [Principal](https://docs.oracle.com/javase/10/docs/api/java/security/Principal.html) object instead: ```java /** From 5e69b5bba418ff2615f94fcb2db49db21388b35f Mon Sep 17 00:00:00 2001 From: Aaron Klish Date: Mon, 25 Feb 2019 16:43:32 -0600 Subject: [PATCH 4/4] Clarified that the principal/security context is wrapped in a User object --- pages/guide/03-security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/guide/03-security.md b/pages/guide/03-security.md index a452de86..2ac25282 100644 --- a/pages/guide/03-security.md +++ b/pages/guide/03-security.md @@ -127,7 +127,7 @@ Filter expression checks are most important when a security rule is tied in some ## User --------------------- -Each request is associated with a user. By default the user is simply an opaque object that wraps an instance of a [SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html) object. +Each request is associated with a `User` object. By default the user is simply an opaque object that wraps an instance of a [SecurityContext](https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.html) object. The `SecurityContext` is created outside the Elide framework in a [JAX-RS](https://jcp.org/en/jsr/detail?id=311) [ContainerRequestFilter](https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ContainerRequestFilter.html):