All Projects â†’ Sytten â†’ nexus-shield

Sytten / nexus-shield

Licence: MIT license
🛡 Nexus plugin to ease the creation of the authorization layer

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to nexus-shield

django-letsagree
A Django application that associates Groups with Terms requiring consent from logged in members.
Stars: ✭ 12 (-86.67%)
Mutual labels:  authorization
AspNetCore-Dynamic-Permission
Dynamic Permission Samples in ASP.NET Core and ASP.NET MVC 5.
Stars: ✭ 19 (-78.89%)
Mutual labels:  authorization
browser-acl
Simple acceess control (ACL) library for the browser inspired by Laravel's guards and policies.
Stars: ✭ 36 (-60%)
Mutual labels:  authorization
bouncer
Token-based authorization and session management for Phoenix (Elixir)
Stars: ✭ 27 (-70%)
Mutual labels:  authorization
huawei-account-demo
Sample code for quickly integrate Huawei ID. HUAWEI Account Kit provides developers with simple, secure, and quick sign-in and authorization functions.
Stars: ✭ 39 (-56.67%)
Mutual labels:  authorization
react-auth-kit
Easily manage Authentication state of users in React-based Apps using Hooks and Higher-order components
Stars: ✭ 177 (+96.67%)
Mutual labels:  authorization
aarbac
An Automated Role Based Access Control .NET framework with T-SQL Query Parser which automatically parse select, insert, update, delete queries based on the logged in user role
Stars: ✭ 18 (-80%)
Mutual labels:  authorization
riam
AWS IAM inspired policy engine in Rust
Stars: ✭ 19 (-78.89%)
Mutual labels:  authorization
react-rbac-ui-manager
react-rbac-ui-manager is a simple RBAC (Role Based Access Control) user interface library based on the material design system using the Material-UI lib.
Stars: ✭ 73 (-18.89%)
Mutual labels:  authorization
bouncer
Authorization Package for AdonisJS
Stars: ✭ 39 (-56.67%)
Mutual labels:  authorization
swift
SWIFT (payments) SDK in GO
Stars: ✭ 18 (-80%)
Mutual labels:  authorization
objection-authorize
isomorphic, "magical" authorization integration with Objection.js 🎉
Stars: ✭ 71 (-21.11%)
Mutual labels:  authorization
mod authnz jwt
An authentication module for Apache httpd using JSON Web Tokens
Stars: ✭ 74 (-17.78%)
Mutual labels:  authorization
oauth2-wechat
微信登录认证授权 Wechat login authorization. This package provides Wechat OAuth 2.0 support for the PHP League's OAuth 2.0 Client
Stars: ✭ 18 (-80%)
Mutual labels:  authorization
server
AuthzForce Server (Community Edition)
Stars: ✭ 48 (-46.67%)
Mutual labels:  authorization
kibana-multitenant-proxy
A proxy behind nginx while before kibana (4.x, 5.x) to provide data isolation for different users
Stars: ✭ 25 (-72.22%)
Mutual labels:  authorization
activity-based-security-framework
Exadel Activity-based Security Framework
Stars: ✭ 17 (-81.11%)
Mutual labels:  authorization
lastkeypair
A serverless SSH certificate authority to control access to machines using IAM and Lambda
Stars: ✭ 39 (-56.67%)
Mutual labels:  authorization
logto
🧑‍🚀 Logto helps you build the sign-in, auth, and user identity within minutes. We provide an OIDC-based identity service and the end-user experience with username, phone number, email, and social sign-in, with extendable multi-language support.
Stars: ✭ 3,421 (+3701.11%)
Mutual labels:  authorization
auth
👤 Authentication and Authorization framework for Fluent.
Stars: ✭ 51 (-43.33%)
Mutual labels:  authorization

nexus-shield

Github Actions codecov npm version

Help Wanted ⚠️

If you are a Typescript expert, I could use a hand on a lingering typing issue when a shield parameter is added to an objectType. Please see the related issue for details. Thanks!

Overview

Nexus Shield is a nexus plugin that helps you create an authorization layer for your application. It is a replacement for the provided authorization plugin. It is heavily inspired by Graphql Shield and reuses most of it's familiar ruling system. It takes full advantage of the type safety provided by nexus.

Install

npm install --save nexus-shield

OR

yarn add nexus-shield

Usage

Nexus configuration

The plugin first needs to be installed in nexus. This will add the new shield parameter. The plugin will work without any provided configuration, but it is recommended to provide one that is relevant to your application. The available parameters are:

  • defaultError: The error that is thrown if the access is denied. See the errors section.
  • defaultRule: Rule that is used if none is specified for a field.
  • hashFunction: Function used to hash the input to provide caching keys.

For example, using an Apollo server:

import { nexusShield, allow } from 'nexus-shield';
import { ForbiddenError } from 'apollo-server';

const schema = makeSchema({
  // ... Rest of the configuration
  plugins: [
    nexusShield({
      defaultError: new ForbiddenError('Not allowed'),
      defaultRule: allow,
    }),
  ],
});

Styles

Two interfaces styles are provided for convenience: Graphql-Shield and Nexus.

Graphql-Shield

rule()((root, args, ctx) => {
  return !!ctx.user;
});

Nexus

ruleType({
  resolve: (root, args, ctx) => {
    return !!ctx.user;
  },
});

Error

  • A rule needs to return a boolean, a Promise<boolean> or throw an Error.
  • Contrary to Graphql-shield, this plugin will NOT catch the errors you throw and will just pass them down to the next plugins and eventually to the server
  • If false is returned, the configured defaultError will be thrown by the plugin.
import { AuthenticationError } from 'apollo-server';

const isAuthenticated = ruleType({
  resolve: (root, args, ctx) => {
    const allowed = !!ctx.user;
    if (!allowed) throw new AuthenticationError('Bearer token required');
    return allowed;
  },
});

Operators

Rules can be combined in a very flexible manner. The plugin provides the following operators:

  • and: Returns true if all rules return true
  • or: Returns true if one rule returns true
  • not: Inverts the result of a rule
  • chain: Same as and, but rules are executed in order
  • race: Same as or, but rules are executed in order
  • deny: Returns false
  • allow: Returns true

Simple example:

import { chain, not, ruleType } from 'nexus-shield';

const hasScope = (scope: string) => {
  return ruleType({
    resolve: (root, args, ctx) => {
      return ctx.user.permissions.includes(scope);
    },
  });
};

const backlist = ruleType({
  resolve: (root, args, ctx) => {
    return ctx.user.token === 'some-token';
  },
});

const viewerIsAuthorized = chain(
  isAuthenticated,
  not(backlist),
  hasScope('products:read')
);

Shield Parameter

To use a rule, it must be assigned to the shield parameter of a field:

export const Product = objectType({
  name: 'Product',
  definition(t) {
    t.id('id');
    t.string('prop', {
      shield: ruleType({
        resolve: (root, args, ctx) => {
          return !!ctx.user;
        },
      }),
    });
  },
});

Type safety

This plugin will try its best to provide typing to the rules.

  • It is preferable to define rules directly in the definition to have access to the full typing of root and args.
  • The ctx is always typed if it was properly configured in nexus makeSchema.
  • If creating generic or partial rules, use the appropriate helpers (see below).
export type Context = {
  user?: { id: string };
};

export const Product = objectType({
  name: 'Product',
  definition(t) {
    t.id('id');
    t.string('ownerId');
    t.string('prop', {
      args: {
        filter: stringArg({ nullable: false }),
      },
      shield: ruleType({
        resolve: (root, args, ctx) => {
          // root => { id: string }, args => { filter: string }, ctx => Context
          return true;
        },
      }),
    });
  },
});

Generic rules

  • Generic rules are rules that do not depend on the type of the root or args.
  • The wrapper generic is provided for this purpose. It will wrap your rule in a generic function.
const isAuthenticated = generic(
  ruleType({
    resolve: (root, args, ctx) => {
      // Only ctx is typed
      return !!ctx.user;
    },
  })
);

// Usage
t.string('prop', {
  shield: isAuthenticated(),
});

Partial rules

  • Partial rules are rules that depend only on the type of the root.
  • The wrapper partial is provided for this purpose. It will wrap your rule in a generic function.
const viewerIsOwner = partial(
  ruleType({
    type: 'Product' // It is also possible to use the generic parameter of `partial`
    resolve: (root, args, ctx) => {
      // Both root and ctx are typed
      return root.ownerId === ctx.user.id;
    },
  })
);

// Usage
t.string('prop', {
  shield: viewerIsOwner(),
});

Combining rules

If you mix and match generic rules with partial rules, you will need to specify the type in the parent helper.

const viewerIsAuthorized = partial<'Product'>(
  chain(isAuthenticated(), viewerIsOwner())
);

However, if you specify it directly in the shield field, there is not need for an helper thus no need for a parameter.

t.string('prop', {
  shield: chain(isAuthenticated(), viewerIsOwner()),
});

Caching

  • The result of a rule can be cached to maximize performances. This is important when using generic or partial rules that require access to external data.
  • The caching is always scoped to the request

The plugin offers 3 levels of caching:

  • NO_CACHE: No caching is done (default)
  • CONTEXTUAL: Use when the rule only depends on the ctx
  • STRICT: Use when the rule depends on the root or args

Usage:

rule({ cache: ShieldCache.STRICT })((root, args, ctx) => {
  return true;
});

ruleType({
  cache: ShieldCache.STRICT,
  resolve: (root, args, ctx) => {
    return !!ctx.user;
  },
});

Known issues / limitations

  • Currently the typing of the shield parameter on objectType doesn't work. Tracked by issue: #50

  • It is not possible to pass directly an objectType to the parameter type of a ruleType. Tracked by issue: graphql-nexus/nexus#451

  • The helpers are necessary to provide strong typing and avoid the propagation of any. See this StackOverflow issue for more on the subject.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].