Giter VIP home page Giter VIP logo

nuxeo-js-client's Introduction

Client Library for Nuxeo API

Jenkins npm version npm downloads Dependency Status devDependency Status

Browser Support thanks to SauceLabs

The Nuxeo JavaScript Client is a JavaScript client library for the Nuxeo Automation and REST API. The library can work in a browser, or in Node.js, using the same API.

This is an on-going project, supported by Nuxeo.

Nuxeo Platform Dependency

The JS Client is compliant with all Nuxeo versions as of LTS 2015.

Getting Started

Installation

Node.js Applications

After installing Node.js, use npm or yarn to install the nuxeo package:

npm install nuxeo

or

yarn add nuxeo
Node.js
var Nuxeo = require('nuxeo');
var nuxeo = new Nuxeo({ ... });

Bower Powered Applications

The nuxeo client can be also installed through bower:

  bower install nuxeo --save

When added to your page, Nuxeo is available as a global variable.

var nuxeo = new Nuxeo({ ... });

Angular Applications

After adding nuxeo through Bower, you can easily create a service that will return a client:

...
.service('nuxeo', function() {
  return new Nuxeo({
    baseURL: 'http://localhost:8080/nuxeo/',
    auth: {
      method: 'basic',
      username: 'Administrator',
      password: 'Administrator'
    }
  });
})
...

To notify Angular to update the UI when a Nuxeo promise has resolved, you can either wrap Nuxeo promises in $q.when() or, the preferred way, configure the Promise library class to be $q.

// wrap promises
...
$q.when(nuxeo.request('/path/').get()).then(function(res) {
  $scope.res = res;
});
// use $q as the Promise library class
...
.service('nuxeo', function($q) {
  Nuxeo.promiseLibrary($q);
  return new Nuxeo({
    baseURL: 'http://localhost:8080/nuxeo/',
    auth: {
      method: 'basic',
      username: 'Administrator',
      password: 'Administrator'
    }
  });
})
...

Angular v2 Applications

After adding nuxeo through npm or yarn to your application, you can use the Nuxeo client directly by requiring the nuxeo module:

const Nuxeo = require('nuxeo');
...
const nuxeo = new Nuxeo({...});
...

Nuxeo works correctly with Angular v2 ZoneAwarePromise Promise library, so the component tree will be re-rendered when a Promise from Nuxeo will resolve.

React Applications

After adding nuxeo through npm or yarn to your application:

var Nuxeo = require('nuxeo');

Documentation

Check out the API documentation.

Examples

Some working examples using the Nuxeo JavaScript Client can be found here.

Deprecated APIs

Nuxeo.oauth2.getAuthorizationURL(baseURL, clientId[, params]) (since 4.0.0)

The getAuthorizationURL(baseURL, clientId[, params]) method is deprecated in favor of the getAuthorizationURL(opts) method. The old arguments are now passed in the opts object, such as:

Nuxeo.oauth2.getAuthorizationURL({ baseURL, clientId, params })

Nuxeo.oauth2.fetchAccessTokenFromAuthorizationCode(baseURL, clientId, code[, params]) (since 4.0.0)

The fetchAccessTokenFromAuthorizationCode(baseURL, clientId, code[, params]) method is deprecated in favor of the fetchAccessTokenFromAuthorizationCode(opts) method. The old arguments are now passed in the opts object, such as:

Nuxeo.oauth2.fetchAccessTokenFromAuthorizationCode({ baseURL, clientId, code, params })

Nuxeo.oauth2.fetchAccessTokenFromJWTToken(baseURL, clientId, jwtToken[, params]) (since 4.0.0)

The fetchAccessTokenFromJWTToken(baseURL, clientId, jwtToken[, params]) method is deprecated in favor of the fetchAccessTokenFromJWTToken(opts) method. The old arguments are now passed in the opts object, such as:

Nuxeo.oauth2.fetchAccessTokenFromJWTToken({ baseURL, clientId, jwtToken, params })

Nuxeo.oauth2.refreshAccessToken(baseURL, clientId, refreshToken[, params]) (since 4.0.0)

The refreshAccessToken(baseURL, clientId, refreshToken[, params]) method is deprecated in favor of the refreshAccessToken(opts) method. The old arguments are now passed in the opts object, such as:

Nuxeo.oauth2.refreshAccessToken({ baseURL, clientId, refreshToken, params })

Base#timeout (since 3.6.0)

The timeout method available on the Base class is deprecated in favor of using directly the httpTimeout or transactionTimeout methods depending of what needs to be configured.

Note that the httpTimeout is in milliseconds while the transactionTimeout is in seconds, so guessing the transactionTimeout from a timeout is a bad idea, you better need to be explicit.

Nuxeo#nuxeoVersion (since 3.5.0)

The nuxeoVersion property of a Nuxeo client instance is deprecated in favor of the serverVersion property that allows correct versions comparison.

The Nuxeo.VERSIONS object is also deprecated in favor of the Nuxeo.SERVER_VERSIONS object.

_Nuxeo#http (since 3.3.0)

The "private" _http method is deprecated in favor of the "public" http method.

Nuxeo#login (since 3.0.0)

The login method is deprecated in favor of the connect method.

Quick Start

This quick start guide will show how to do basics operations using the client.

Authentication

The authentication method to be used is defined when creating a client:

var nuxeo = new Nuxeo({
  auth: {
    method: ...,
    ...
  }
});

The client supports different authentication methods matching the ones available on the Nuxeo Platform.

Basic Authentication

The simplest one allowing to authenticate with a username and password.

var nuxeo = new Nuxeo({
  auth: {
    method: 'basic',
    username: 'Administrator',
    password: 'Administrator'
  }
});

Portal Authenticaton

If the Portal Authentication is configured on the Nuxeo Platform, you can authenticate with the portal method.

var nuxeo = new Nuxeo({
  auth: {
    method: 'portal',
    username: 'joe',
    secret: 'shared-secret-from-server'
  }
});

Token Authentication

To authenticate through a token from the Nuxeo Server:

var nuxeo = new Nuxeo({
  auth: {
    method: 'token',
    token: 'a-token'
  }
});

There is a utility method Nuxeo#requestAuthenticationToken to retrieve a token from a Nuxeo Server using the configured authentication method. For instance, a typical flow would be:

var nuxeo = new Nuxeo({
  auth: {
    method: 'basic',
    username: 'Administrator',
    password: 'Administrator'
  }
});

nuxeo.requestAuthenticationToken('My App', deviceUID, deviceName, 'rw')
  .then(function(token) {
    nuxeo = new Nuxeo({
      auth: {
        method: 'token',
        token: token
      }
    });

    // do something with the new `nuxeo` client using token authentication
    // store the token, and next time you need to create a client, use it
  })
  .catch(function(err) {
    throw err;
  });

OAuth2 Authorization and Bearer Token Authentication

Since Nuxeo Platform 9.2, you can use OAuth2 authorization through the JS client.

For more information on OAuth2 server side, see Using OAuth2.

Assuming you already have an access token, you can configure the client:

var nuxeo = new Nuxeo({
  auth: {
    method: 'bearerToken',
    token: access_token,
    clientId: 'my-app', // optional OAuth2 client ID to refresh the access token
    clientSecret: 'my-secret', // required if the client defines a secret
  }
});

The bearertoken method supports the token being a simple string (an access token) or a full token object such as:

{
  "access_token":"H8dXDdEW9U2jJnFDh6lJJ74AHRzCyG4D",
  "token_type":"bearer",
  "expires_in":3600,
  "refresh_token":"Amz8JlyglhGWDmYHMYS5EnTTFUFAwZLiHG4aqQDfkwUNunSMpTTSFUmvprX3WdSF"
}

If the token is a full token object (ie. with a refresh_token key) and a clientId is configured on the auth object, the client will try automatically to refresh the access token if it's expired.

OAuth2 Flow

A typical OAuth2 flow with the Nuxeo Platform would be:

Retrieving Authorization Code

Generate a "log in" link to be used in a browser, such as:

http://localhost:8080/nuxeo/oauth2/authorize?client_id=CLIENT_ID[&client_secret=CLIENT_SECRET]&response_type=code&redirect_uri=REDIRECT_URI

The user sees the login page then, after being logged in, the authorization prompt for the application.

If the user grants access, the Nuxeo Platform redirects the user back to the application:

http://localhost:8000/authorize?code=AUTH_CODE

Retrieving Access Token

The client exchanges the authorization code for an access token:

POST http://localhost:8080/nuxeo/oauth2/token
  grant_type=authorization_code
  code=AUTH_CODE
  redirect_uri=REDIRECT_URI
  client_id=CLIENT_ID
  client_secret=CLIENT_SECRET

The Nuxeo Platform replies with an access token:

{
  "access_token":"H8dXDdEW9U2jJnFDh6lJJ74AHRzCyG4D",
  "token_type":"bearer",
  "expires_in":3600,
  "refresh_token":"Amz8JlyglhGWDmYHMYS5EnTTFUFAwZLiHG4aqQDfkwUNunSMpTTSFUmvprX3WdSF"
}

There are some utility methods on the client to help you with this flow:

Nuxeo.oauth2.getAuthorizationURL(opts)

Returns the OAuth2 authorization URL for the given opts object, containing baseURL, clientId, optional clientSecret and optional params.

var authorizationURL = Nuxeo.oauth2.getAuthorizationURL({
  baseURL: 'http://localhost:8080/nuxeo',
  clientId: 'my-app',
  clientSecret: 'my-secret', // required if the client defines a secret
  params: {
    state: 'xyz',
    redirect_uri: 'http://localhost:8000/authorize',
  }
});
console.log(authorizationURL); // http://localhost:8080/nuxeo/oauth2/authorize?client_id=my-app&response_type=code&state=xyz&redirect_uri=http://localhost:8000/authorize

Nuxeo.oauth2.fetchAccessTokenFromAuthorizationCode(opts)

Fetches an OAuth2 access token for the given opts object containing baseURL, clientId, code, optional clientSecret and optional params.

var code = ...
Nuxeo.oauth2.fetchAccessTokenFromAuthorizationCode({
  baseURL: 'http://localhost:8080/nuxeo',
  clientId: 'my-app',
  clientSecret: 'my-secret', // required if the client defines a secret
  code: code,
  params: {
    redirect_uri: 'http://localhost:8000/authorize',
  }
}).then(function(token) {
  // do something with the access token
  var nuxeo = new Nuxeo({
    auth: {
      method: 'bearerToken',
      token: token,
      clientId: 'my-app', // optional OAuth2 client ID to refresh the access token
      clientSecret: 'my-secret', // required if the client defines a secret
    }
  });
});

Nuxeo.oauth2.fetchAccessTokenFromJWTToken(opts)

Fetches an OAuth2 access token for the given opts object containing baseURL, clientId, jwtToken, optional clientSecret and optional params.

var jwtToken = ...
Nuxeo.oauth2.fetchAccessTokenFromJWTToken({
  baseURL: 'http://localhost:8080/nuxeo',
  clientId: 'my-app',
  clientSecret: 'my-secret', // required if the client defines a secret
  jwtToken: jwtToken,
  params: {
    redirect_uri: 'http://localhost:8000/authorize',
  }
}).then(function(token) {
  // do something with the access token
  var nuxeo = new Nuxeo({
    auth: {
      method: 'bearerToken',
      token: token
    }
  });
});

Nuxeo.oauth2.refreshAccessToken(optsbaseURL, clientId, refreshToken[, params])

Manually refresh an access token for the given opts object containing baseURL, clientId, refreshToken, optional clientSecret and optional params.

var refreshToken = ...
Nuxeo.oauth2.refreshAccessToken({
  baseURL: 'http://localhost:8080/nuxeo',
  clientId: 'my-app',
  clientSecret: 'my-secret', // required if the client defines a secret
  refreshToken: refreshToken,
}).then(function(token) {
    console.log(token); // refreshed access token
});

Creating a Client

var nuxeo = new Nuxeo({
  auth: {
    method: 'basic',
    username: 'Administrator',
    password: 'Administrator'
  }
});

To connect to a different Nuxeo Platform Instance, you can use the following:

var nuxeo = new Nuxeo({
  baseURL: 'http://demo.nuxeo.com/nuxeo/',
  auth: {
    method: 'basic',
    username: 'Administrator',
    password: 'Administrator'
  }
});

Promise Based Calls

All API calls made on the server return a Promise object.

nuxeo.operation('Document.GetChildren')
  .input('/')
  .execute()
  .then(function(docs) {
    // work with docs
  })
  .catch(function(error) {
    // something went wrong
    throw error;
  });

When something went wrong, the error is an Error object with a response field containing the whole response.

Connecting to a Nuxeo Server

After creating a Client, you can connect to a Nuxeo Server by using the connect method. This method returns a Promise which is resolved with the connected client.

var nuxeo = new Nuxeo({ ... });
nuxeo.connect()
  .then(function(client){
    // client.connected === true
    // client === nuxeo
    console.log('Connected OK!');
  })
  .catch(function(error) {
    // wrong credentials / auth method / ...
    throw error;
  });

Current User

The connect method fills the user property of the client. user is a full User object.

var nuxeo = new Nuxeo({ ... });
nuxeo.connect()
  .then(function(client){
    // client.user.id === 'Administrator'
    console.log(client.user);
  })
  .catch(function(error) {
    // wrong credentials / auth method / ...
    throw error;
  });

Nuxeo Server version

The connect method fills the serverVersion property of the client.

var nuxeo = new Nuxeo({ ... });
nuxeo.connect()
  .then(function(client){
    console.log(client.serverVersion); // '9.10'
  })
  .catch(function(error) {
    // wrong credentials / auth method / ...
    throw error;
  });

Some constants are available in the Nuxeo object for supported LTS versions:

Nuxeo.SERVER_VERSIONS.LTS_2017; // for '9.10';
Nuxeo.SERVER_VERSIONS.LTS_2019; // for '10.10';

You can use them to easily make different calls according to the target version:

...
if (nuxeo.serverVersion.lt(Nuxeo.SERVER_VERSIONS.LTS_2017)) {
  // do something on versions before LTS 2016
} else {
  // do something else
}
...

See the ServerVersion documentation.

Note that the nuxeoVersion property is deprecated but it is still filled with the Nuxeo Server version.

Operation

Operation object allows you to execute an operation (or operation chain).

See the Operation documentation.

Samples

Call an operation to create a new folder in the Root document

nuxeo.operation('Document.Create')
  .params({
    type: 'Folder',
    name: 'My Folder',
    properties: 'dc:title=My Folder \ndc:description=A Simple Folder'
  })
  .input('/')
  .execute()
  .then(function(doc) {
    console.log('Created ' + doc.title + ' folder');
  })
  .catch(function(error) {
    throw error;
  });

Request

The Request object allows you to call the Nuxeo REST API.

See the Request documentation.

Samples

Fetch the Administrator user

nuxeo.request('user/Administrator')
  .get()
  .then(function(user) {
    console.log(user);
  })
  .catch(function(error) {
    throw error;
  });

Fetch the whole list of Natures

nuxeo.request('directory/nature')
  .get()
  .then(function(data) {
    console.log(JSON.stringify(data.entries, null, 2))
  })
  .catch(function(error) {
    throw error
  });

Repository

The Repository object allows you to work with document.

See the Repository documentation.

Samples

Create a Repository object

var defaultRepository = nuxeo.repository(); // 'default' repository
...
var testRepository = nuxeo.repository('test'); // 'test' repository
...

Fetch the Root document

nuxeo.repository().fetch('/')
  .then(function(doc) {
    console.log(doc);
  })
  .catch(function(error) {
    throw error;
  });

Create a new folder

var newFolder = {
  'entity-type': 'document',
  name: 'a-folder',
  type: 'Folder',
  properties: {
    'dc:title': 'foo'
  }
};
nuxeo.repository()
  .create('/', newFolder)
  .then(function(doc) {
    console.log(doc);
  })
  .catch(function(error) {
    throw error;
  });

Delete a document

nuxeo.repository()
  .delete('/a-folder')
  .then(function(res) {
    // res.status === 204
  });

Document

Repository object returns and works with Document objects. Document objects exposes a simpler API to work with a document.

See the Document documentation.

Samples

Retrieve a Document object

nuxeo.repository()
  .fetch('/')
  .then(function(doc) {
    // doc instanceof Nuxeo.Document === true
  })
  .catch(function(error) {
    throw error;
  });

Set a document property

doc.set({ 'dc:title': 'foo' });

Get a document property

doc.get('dc:title');

Save an updated document

nuxeo.repository()
  .fetch('/')
  .then(function(doc) {
    // doc.title !== 'foo'
    doc.set({ 'dc:title': 'foo' });
    return doc.save();
  })
  .then(function(doc) {
    // doc.title === 'foo'
  })
  .catch(function(error) {
    throw error;
  });

Fetch the main Blob of a document

doc.fetchBlob()
  .then(function(res) {
    // in the browser, use res.blob() to work with the converted PDF
    // in Node.js, use res.body
  });

Convert a document main Blob to PDF

doc.convert({ format: 'pdf' })
  .then(function(res) {
    // in the browser, use res.blob() to work with the converted PDF
    // in Node.js, use res.body
  });

Fetch the 'thumbnail' rendition

doc.fetchRendition('thumbnail')
  .then(function(res) {
    // in the browser, use res.blob() to work with the rendition
    // in Node.js, use res.body
  });

Start a workflow

doc.startWorkflow('SerialDocumentReview')
  .then(function(workflow) {
    // workflow instance of Nuxeo.Workflow
  });

Complete a workflow task

workflow.fetchTasks()
  .then(function(tasks) {
    return tasks[0];
  })
  .then(function(tasks) {
    task.variable('participants', ['user:Administrator'])
      .variable('assignees', ['user:Administrator'])
      .variable('end_date', '2011-10-23T12:00:00.00Z');
    return task.complete('start_review', { comment: 'a comment' });
  })
  .then(function(task) {
    // task.state === 'ended'
  })

BatchUpload

The BatchUpload object allows you to upload blobs to a Nuxeo Platform instance, and use them as operation input or as document property value.

See the BatchUpload documentation.

Samples

Create a Nuxeo.Blob to be uploaded

// on the browser, assuming you have a File object 'file'
var blob = new Nuxeo.Blob({ content: file });
// the name, mimeType and size will be extracted from the file object itself, you can still override them.
...
// on Node.js, assuming you have a Stream 'file'
var blob = new Nuxeo.Blob({ content: file, name: 'foo.txt', mimeType: 'plain/text', size: 10 })

Upload a blob

nuxeo.batchUpload()
  .upload(blob)
  .then(function(res) {
    // res.blob instanceof Nuxeo.BatchBlob
    console.log(res.blob);
  })
  .catch(function(error) {
    throw error;
  });

Attach an uploaded blob to a document

nuxeo.batchUpload()
  .upload(blob)
  .then(function(res) {
    return nuxeo.operation('Blob.AttachOnDocument')
      .param('document', '/a-file')
      .input(res.blob)
      .execute();
  })
  .then(function() {
    return nuxeo.repository().fetch('/a-file', { schemas: ['dublincore', 'file']});
  })
  .then(function(doc) {
    console.log(doc.get('file:content'));
  })
  .catch(function(error) {
    throw error;
  });

Users

The Users object allows you to work with users.

See the Users and User documentation.

Samples

Fetch an user

nuxeo.users()
  .fetch('Administrator')
  .then(function(user) {
    // user.id === 'Administrator'
  });

Create a new user

var newUser = {
  properties: {
    username: 'leela',
    firstName: 'Leela',
    company: 'Futurama',
    email: '[email protected]'
  },
};
nuxeo.users()
  .create(newUser)
  .then(function(user) {
    // user.id === 'leela'
  });

Delete an user

nuxeo.users()
  .delete('leela').then(function(res) {
    // res.status === 204
  });

Groups

The Groups object allows you to work with groups.

See the Groups and Group documentation.

Samples

Fetch a group

nuxeo.groups().fetch('administrators')
  .then(function(group) {
    // group.groupname === 'administrators'
  });

Create a new group

var newGroup = {
  groupname: 'foo',
  grouplabel: 'Foo'
};
nuxeo.groups()
  .create(newGroup)
  .then(function(group) {
    // group.groupname === 'foo';
  });

Delete a group

nuxeo.groups()
  .delete('foo').then(function(res) {
    // res.status === 204
  });

Directory

The Directory object allows you to work with directories.

See the Directory and DirectoryEntry documentation.

Samples

Fetch all entries of a directory

nuxeo.directory('nature')
  .fetchAll()
  .then(function(entries) {
    // entries instance of Array
  });

Fetch a given directory entry

nuxeo.directory('nature')
  .fetch('article')
  .then(function(entry) {
    // entry.directoryName === 'nature'
    // entry.properties.id === 'article'
  });

Create a new directory entry

var newEntry = {
  properties: {
    id: 'foo',
    label: 'Foo'
  },
};
nuxeo.directory('nature')
  .create(newEntry)
  .then(function(entry) {
    // entry.directoryName === 'nature'
    // entry.properties.id === 'foo'
  });

Delete a directory entry

nuxeo.directory('nature')
 .delete('foo')
 .then(function(res) {
   // res.status === 204
 });

Contributing

See our contribution documentation.

Requirements

Setup

Install Node.js and then use yarn to install all the required libraries:

$ git clone https://github.com/nuxeo/nuxeo-js-client
$ cd nuxeo-js-client
$ yarn

Test

A Nuxeo Platform instance needs to be running on http://localhost:8080/nuxeo for the tests to be run.

Tests can be launched on Node.js with:

$ yarn test:node

For testing the browser client (tests are run on Chrome by default):

$ yarn test:browser

To run both Node.js and browser tests:

$ yarn test

Reporting Issues

You can follow the developments in the Nuxeo JS Client project of our JIRA bug tracker: https://jira.nuxeo.com/browse/NXJS.

You can report issues on answers.nuxeo.com.

Big Thanks

Cross-browser Testing Platform and Open Source <3 Provided by Sauce Labs

License

Apache License 2.0 Copyright (c) Nuxeo SA

About Nuxeo

Nuxeo dramatically improves how content-based applications are built, managed and deployed, making customers more agile, innovative and successful. Nuxeo provides a next generation, enterprise ready platform for building traditional and cutting-edge content oriented applications. Combining a powerful application development environment with SaaS-based tools and a modular architecture, the Nuxeo Platform and Products provide clear business value to some of the most recognizable brands including Verizon, Electronic Arts, Sharp, FICO, the U.S. Navy, and Boeing. Nuxeo is headquartered in New York and Paris. More information is available at www.nuxeo.com.

nuxeo-js-client's People

Contributors

akervern avatar aldebout avatar ataillefer avatar bchauvin avatar bstefanescu avatar denis-yomura avatar dependabot[bot] avatar ffjdm avatar gustavofp avatar hsablonniere avatar jcarsique avatar kevinleturc avatar kfrapin avatar nournuxeo avatar nuxeo-platform-jx-bot avatar nuxeojenkins avatar pgmillon avatar rsalem07 avatar sguitter avatar spazzmarticus avatar thibarg avatar tingletech avatar troger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nuxeo-js-client's Issues

Unable to verify the first certificate

I am trying to update nuxeo client for my application which was using version: 0.4.0. Once I update it to latest, I'm getting following error:

FetchError: request to https://my-intended-url failed, reason: unable to verify the first certificate
at ClientRequest.req.on.err (C:\application\node_modules\node-fetch-npm\src\index.js:68:14)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:189:7)
at TLSSocket.socketErrorListener (_http_client.js:358:9)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:189:7)
at emitErrorNT (net.js:1280:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)

How to resolve this issue?

Note: for my development I'm using http://localhost which is pointing to https://url as base url and the base url is having valid certificate and I'm using method 'portal' with username and secret. This config working fine with version 0.4.0

Client issue with oauth2 and ANONYMOUS_AUTH

Hi,

from a vanilla JS page, the call to authorizationURL does not redirect to login but directly to the configured redirect_uri
the call to fetchAccessTokenFromAuthorizationCode indeed creates a token ... for Guest user

In the PluggableAuthenticationService configuration, OAUTH2_AUTH is always before ANONYMOUS_AUTH in extension points chain or already overridden specificChains

What's wrong ?
PS : default auth is Shibboleth

Nuxeo api automation does not support OAUTH2 authentication

Hi @troger , @kevinleturc

I try nuxeo-js-client with LTS2021 and I ca not login through OAUTH2 token.
I always get http 401 statut.

curl -H "Authorization:Bearer 012453xxgqzl45" -X POST https://localhost:8080/nuxeo/api/v1/automation/login

Response :

<!doctype html><html lang="en"><head><title>HTTP Status 401 ? Unauthorized</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 401 ? Unauthorized</h1></body></html>%

The thing is why after using oauth2.fetchAccessTokenFromJWTToken and connected (function connect() ) with have to connect to the cmis and the automation?
Look at here :

finalOptions.url = join(this._automationURL, 'login');

When I try Basic AUTH, the are no problem, but the thing is, I'm connecting to nuxeo-js-client through OAUTH2 token.

On my server side I have my auth.xml set like :

...
<specificAuthenticationChain name="RestAPI">
                        <urlPatterns>
                                <url>(.*)/api/v.*</url>
                        </urlPatterns>
                        <replacementChain>
                                <plugin>AUTOMATION_BASIC_AUTH</plugin>
                                <plugin>BASIC_AUTH</plugin>
                                <plugin>PORTAL_AUTH</plugin>
                                <plugin>TOKEN_AUTH</plugin>
                                <plugin>OAUTH2_AUTH</plugin>
                                <plugin>JWT_AUTH</plugin>
                                <!-- <plugin>ANONYMOUS_AUTH</plugin> -->
                        </replacementChain>
                </specificAuthenticationChain>

                <specificAuthenticationChain name="ATOM_CMIS">
                        <urlPatterns>
                                <url>(.*)/atom/cmis(/.*)?</url>
                                <url>(.*)/atom/cmis10(/.*)?</url>
                        </urlPatterns>
                        <replacementChain>
                                <plugin>BASIC_AUTH</plugin>
                                <plugin>PORTAL_AUTH</plugin>
                                <plugin>TOKEN_AUTH</plugin>
                        </replacementChain>
                </specificAuthenticationChain>

                <specificAuthenticationChain name="JSON_CMIS">
                        <urlPatterns>
                          <url>(.*)/json/cmis(/.*)?</url>
                        </urlPatterns>
                        <replacementChain>
                                <plugin>BASIC_AUTH</plugin>
                                <plugin>PORTAL_AUTH</plugin>
                                <plugin>TOKEN_AUTH</plugin>
                        </replacementChain>
                  </specificAuthenticationChain>

                <specificAuthenticationChain name="TokenAuth">
                        <headers>
                          <header name="X-Authentication-Token">.*</header>
                        </headers>
                        <replacementChain>
                                <plugin>TOKEN_AUTH</plugin>
                                <plugin>AUTOMATION_BASIC_AUTH</plugin>
                        </replacementChain>
                  </specificAuthenticationChain>
...

Thanks for your help

Unable to pass 'mode' option to fetch function

Hi.

I have a react application that is trying to connect to the nuxeo ui.
Nuxeo is launched by a docker command:

docker run --name mynuxeo --rm -ti -p 8080:8080 -e NUXEO_PACKAGES="nuxeo-web-ui nuxeo-showcase-content nuxeo-template-rendering nuxeo-template-rendering-samples" -e NUXEO_CUSTOM_PARAM="org.nuxeo.dev=true\nallowOrigin=http://localhost:3000\nallowSubdomains=true\nsupportedMethods=GET,POST,HEAD,OPTIONS" nuxeo:9.10

and accessible in the browser at http://172.17.0.2:8080/nuxeo/ or http://localhost:8080/nuxeo/.

The react application is created by create-react-app.
My package.json:

{
  "name": "react-nuxeo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.4.0",
    "@testing-library/user-event": "^7.1.2",
    "nuxeo": "^3.15.0",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-router-dom": "^5.1.2",
    "react-scripts": "^3.3.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Inside of the react application, I have the next code:

  let nuxeo = new Nuxeo({
      baseURL: 'http://172.17.0.2:8080/nuxeo',
      auth: {
        method: 'basic',
        username: 'Administrator',
        password: 'Administrator'
      }
    });

    nuxeo.connect({
      mode: 'no-cors',
      headers: {
        'Access-Control-Allow-Origin': '*'
      }
    })
      .then((client) => this.setState({ nuxeo_status: 'connected' }))
      .catch((error) => this.setState({ nuxeo_status: 'error' }));

Which is producing next error:
image

I believe the root of the problem is in nuxeo.js file at line 126:

  const fetchOptions = {
        method: options.method,
        headers: options.headers,
        body: options.body,
        signal: options.signal,
      };

Because inside of the options I'm passing mode option which is not copied to the fetchOptions

image

When I manually edit nuxeo.js (inside my node_modules) to pass the mode option it fixes the CORS problem:

 const fetchOptions = {
        method: options.method,
        headers: options.headers,
        body: options.body,
        signal: options.signal,
        mode: options.mode
      };

Can you please add the ability to pass mode option?

tests fail with out-of-the-box Nuxeo and nuxeo-js-client

I'm on macOS Catalina. If I have a docker image running an untouched Nuxeo on port 8080 and I run yarn test:node, I get two failures:

  1) Multi Repository
       "before all" hook in "Multi Repository":
     Error: Internal Server Error
      at /Users/trott/nuxeo-js-client/lib/nuxeo.js:159:27
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:93:5)

  2) Operation
       #execute
         should execute an operation with an input being
           non-existing document:
     Error: Method Not Allowed
      at /Users/trott/nuxeo-js-client/lib/nuxeo.js:159:27
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:93:5)



error Command failed with exit code 2.

I'm running Node.js 15.4.0.

Just me? Or others can replicate this?

Parallel requests

Hi,

I am trying to connect with my nodeJS application to Nuxeo with the help of this library.
I am receiving several requests from an external system and I am trying to access Nuxeo. As I am receiving multiple requests simultaneously, I am sending multiple requests with the same connection to Nuxeo at the same time.

It seems, that this is not possible as I am receiving strange results.
I've now created a new connection for each request. This is approach is working, but is much slower.
It seems that the lib is not stateless. Is there a better way to achieve my goal?

Add Requesting an Access Token with a JWT

Hi @troger ,

I open a new issue to make an evolution of nuxeo-js-client about my question : https://answers.nuxeo.com/general/q/f89b2c3d6f594909b5a6bcb8e2ceff0c/nuxeo-js-client-OAuth-2-JWT-Flow

In nuxeo/lib/oauth2.js, in const oauth2 = ... can you add this ?

/**
   * Fetches an OAuth2 access token.
   * @param {string} [baseURL] - Base URL of the Nuxeo Platform.
   * @param {string} [clientId] - The OAuth2 client id.
   * @param {string} [jwtToken] - An JSON web token.
   * @param {object} [params] - Optional parameters.
   * @returns {string}
   */
  fetchAccessToken: (baseURL, clientId, jwtToken, params = {}) => {
    if (!baseURL) {
      throw new Error('Missing `baseURL` argument');
    }
    if (!clientId) {
      throw new Error('Missing `clientId` argument');
    }
    if (!jwtToken) {
      throw new Error('Missing `jwtToken` argument');
    }

    const defaultParams = { assertion, grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', client_id: clientId };
    const body = extend(true, defaultParams, params);
    return fetchAccessToken(baseURL, body);
  }

In nuxeo/nuxeo.js, var oauth2 = ... add this too.

/**
   * Fetches an OAuth2 access token.
   * @param {string} [baseURL] - Base URL of the Nuxeo Platform.
   * @param {string} [clientId] - The OAuth2 client id.
   * @param {string} [jwtToken] - An JSON web token.
   * @param {object} [params] - Optional parameters.
   * @returns {string}
   */
  fetchAccessToken: (baseURL, clientId, jwtToken, params = {}) => {
    if (!baseURL) {
      throw new Error('Missing `baseURL` argument');
    }
    if (!clientId) {
      throw new Error('Missing `clientId` argument');
    }
    if (!jwtToken) {
      throw new Error('Missing `jwtToken` argument');
    }

    const defaultParams = { assertion, grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', client_id: clientId };
    const body = extend(true, defaultParams, params);
    return fetchAccessToken(baseURL, body);
  }

==Update==
According this issue : https://answers.nuxeo.com/general/q/75fb1d38fbc048f59cf01d895f004335/Requesting-an-access-token-with-a-jwt, it seems that grant_type and assertion is not supported yet in nuxeo ? I saw in code package org.nuxeo.ecm.platform.oauth2.Constants and org.nuxeo.ecm.platform.oauth2.NuxeoOAuth2Servlet @troger is the main contributor

Thanks for your reply

Nuxeo client breaking Angular 7 app

Hi,

Unable to run angular 7 app after implements nuxeo libs and service.
It breaks the app litteraly on any browser (FF65, Chromium73 and latest Safari).

index.js:1 Uncaught ReferenceError: process is not defined at Object../node_modules/promise-queue/index.js (index.js:1) at __webpack_require__ (bootstrap:76) at Object../node_modules/nuxeo/lib/upload/batch.js (batch.js:5) at __webpack_require__ (bootstrap:76) at Object../node_modules/nuxeo/lib/operation.js (operation.js:7) at __webpack_require__ (bootstrap:76) at Object../node_modules/nuxeo/lib/nuxeo.js (nuxeo.js:4) at __webpack_require__ (bootstrap:76) at Object../node_modules/nuxeo/lib/index.js (index.js:1) at __webpack_require__ (bootstrap:76) ./node_modules/promise-queue/index.js @ index.js:1 __webpack_require__ @ bootstrap:76 ./node_modules/nuxeo/lib/upload/batch.js @ batch.js:5 __webpack_require__ @ bootstrap:76 ./node_modules/nuxeo/lib/operation.js @ operation.js:7 __webpack_require__ @ bootstrap:76 ./node_modules/nuxeo/lib/nuxeo.js @ nuxeo.js:4 __webpack_require__ @ bootstrap:76 ./node_modules/nuxeo/lib/index.js @ index.js:1 __webpack_require__ @ bootstrap:76 ./src/app/nuxeo.service.ts @ DynamicFlatNode.ts:8 __webpack_require__ @ bootstrap:76 ./src/app/app.module.ts @ app.component.ts:176 __webpack_require__ @ bootstrap:76 ./src/main.ts @ environment.ts:15 __webpack_require__ @ bootstrap:76 0 @ main.ts:12 __webpack_require__ @ bootstrap:76 checkDeferredModules @ bootstrap:43 webpackJsonpCallback @ bootstrap:30 (anonymous) @ main.js:1

Thanks for help

Unable to connect by 'nuxeo.connect' method

Hi.

I have a react application that is trying to connect to the nuxeo ui.
Nuxeo is launched by a docker command:

docker run --name mynuxeo --rm -ti -p 8080:8080 -e NUXEO_PACKAGES="nuxeo-web-ui nuxeo-showcase-content nuxeo-template-rendering nuxeo-template-rendering-samples" -e NUXEO_CUSTOM_PARAM="org.nuxeo.dev=true\nallowOrigin=http://localhost:3000\nallowSubdomains=true\nsupportedMethods=GET,POST,HEAD,OPTIONS" nuxeo:9.10

and accessible in the browser at http://172.17.0.2:8080/nuxeo/ or http://localhost:8080/nuxeo/.

The react application is created by create-react-app.
My package.json:

{
  "name": "react-nuxeo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.4.0",
    "@testing-library/user-event": "^7.1.2",
    "nuxeo": "^3.15.0",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-router-dom": "^5.1.2",
    "react-scripts": "^3.3.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Inside of the react application, I have the next code:

  let nuxeo = new Nuxeo({
      baseURL: 'http://172.17.0.2:8080/nuxeo',
      auth: {
        method: 'basic',
        username: 'Administrator',
        password: 'Administrator'
      }
    });

    nuxeo.connect({
      mode: 'no-cors',
      headers: {
        'Access-Control-Allow-Origin': '*'
      }
    })
      .then((client) => this.setState({ nuxeo_status: 'connected' }))
      .catch((error) => this.setState({ nuxeo_status: 'error' }));

Which is producing the next error:

image

Request params are next:

image

Is there a way to fix this?

Documentation for Nuxeo.http

I couldn't find documentation for the options of Nuxeo.http.

I was able to get a lot of them by reading the source but some of the mechanisms are still escaping me.

For example, using json: true, I get errors at the unmarshalling step and I'm not able to understand why. Setting resolveWithFullResponse: true goes around the problem but everything feels a bit like black magic.

Do you have an internal resource that could help start this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.