GithubHelp home page GithubHelp logo

jaredhanson / passport-openidconnect Goto Github PK

View Code? Open in Web Editor NEW
186.0 15.0 171.0 232 KB

OpenID Connect authentication strategy for Passport and Node.js.

Home Page: https://www.passportjs.org/packages/passport-openidconnect/?utm_source=github&utm_medium=referral&utm_campaign=passport-openidconnect&utm_content=about

License: MIT License

JavaScript 99.79% Makefile 0.21%
passport openid-connect oauth2

passport-openidconnect's Introduction

passport-openidconnect

Passport strategy for authenticating with OpenID Connect.

This module lets you authenticate using OpenID Connect in your Node.js applications. By plugging into Passport, OpenID Connect-based sign in can be easily and unobtrusively integrated into any application or framework that supports Connect-style middleware, including Express.

❤️ Sponsors

Install

$ npm install passport-openidconnect

Usage

Configure Strategy

The OpenID Connect authentication strategy authenticates users using their account at an OpenID Provider (OP). The strategy needs to be configured with the provider's endpoints, as well as a client ID and secret that has been issued by the provider to the app. Consult the provider's documentation for the locations of these endpoints and instructions on how to register a client.

The strategy takes a verify function as an argument, which accepts issuer and profile as arguments. issuer is set to an identifier for the OP. profile contains the user's profile information stored in their account at the OP. When authenticating a user, this strategy uses the OpenID Connect protocol to obtain this information via a sequence of redirects and back-channel HTTP requests to the OP.

The verify function is responsible for determining the user to which the account at the OP belongs. In cases where the account is logging in for the first time, a new user record is typically created automatically. On subsequent logins, the existing user record will be found via its relation to the OP account.

Because the verify function is supplied by the application, the app is free to use any database of its choosing. The example below illustrates usage of a SQL database.

var OpenIDConnectStrategy = require('passport-openidconnect');

passport.use(new OpenIDConnectStrategy({
    issuer: 'https://server.example.com',
    authorizationURL: 'https://server.example.com/authorize',
    tokenURL: 'https://server.example.com/token',
    userInfoURL: 'https://server.example.com/userinfo',
    clientID: process.env['CLIENT_ID'],
    clientSecret: process.env['CLIENT_SECRET'],
    callbackURL: 'https://client.example.org/cb'
  },
  function verify(issuer, profile, cb) {
    db.get('SELECT * FROM federated_credentials WHERE provider = ? AND subject = ?', [
      issuer,
      profile.id
    ], function(err, cred) {
      if (err) { return cb(err); }
      
      if (!cred) {
        // The account at the OpenID Provider (OP) has not logged in to this app
        // before.  Create a new user account and associate it with the account
        // at the OP.
        db.run('INSERT INTO users (name) VALUES (?)', [
          profile.displayName
        ], function(err) {
          if (err) { return cb(err); }
          
          var id = this.lastID;
          db.run('INSERT INTO federated_credentials (user_id, provider, subject) VALUES (?, ?, ?)', [
            id,
            issuer,
            profile.id
          ], function(err) {
            if (err) { return cb(err); }
            var user = {
              id: id,
              name: profile.displayName
            };
            return cb(null, user);
          });
        });
      } else {
        // The account at the OpenID Provider (OP) has previously logged in to
        // the app.  Get the user account associated with the account at the OP
        // and log the user in.
        db.get('SELECT * FROM users WHERE id = ?', [ cred.user_id ], function(err, row) {
          if (err) { return cb(err); }
          if (!row) { return cb(null, false); }
          return cb(null, row);
        });
      }
    });
  }
));

Define Routes

Two routes are needed in order to allow users to log in with their account at an OP. The first route redirects the user to the OP, where they will authenticate:

app.get('/login', passport.authenticate('openidconnect'));

The second route processes the authentication response and logs the user in, when the OP redirects the user back to the app:

app.get('/cb',
  passport.authenticate('openidconnect', { failureRedirect: '/login', failureMessage: true }),
  function(req, res) {
    res.redirect('/');
  });

Examples

  • todos-express-openidconnect

    Illustrates how to use the OpenID Connect strategy within an Express application.

  • todos-express-auth0

    Illustrates how to use the OpenID Connect strategy to integrate with Auth0 in an Express application. For developers new to Passport and getting started, a tutorial is available.

License

The MIT License

Copyright (c) 2011-2022 Jared Hanson <https://www.jaredhanson.me/>

passport-openidconnect's People

Contributors

agiera avatar blackfaded avatar doug-numetric avatar dschenkelman avatar fruitl00p avatar itsjw avatar jaredhanson avatar makuga01 avatar sd65 avatar siacomuzzi avatar

Stargazers

 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  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  avatar  avatar  avatar  avatar

Watchers

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

passport-openidconnect's Issues

Working Sample

This is a question. Does anybody have a working sample of using this? I have a openid connect auth server in place using another tech and I'd like to use this lib to connect to it with an outside nodejs app. A sample would be handy. Thanks!

Ability to support additional parameters?

I was wondering would you accept a PR to support an additional parameters object as part of the Strategy options?

I've been using the package to authenticate with OneLogin, and it works well, but in order to return custom attributes it requires the addition of a resource attribute to params.

Is this project still alive?

Looks like the project is on hold for a while. Can you please share if we can depend on this project or if we should switch to some different library.

Is there anyone who can elaborate on the production readiness of this library as it is still a version 0.0.1 on npm?

Looking forward to a reply.

Logout

How does one retrieve id_token for logging out from the provider? It should be setted to id_token_hint query parameter in the end session -endpoint.

Dynamic callback URL

Can the callback URL be set dynamically, in the authenticate() method, similarly to the option in FacebookStrategy (see some examples in jaredhanson/passport-facebook#2):

app.get('/login',
passport.authenticate('facebook', {
callbackURL:"/auth/callback",
successRedirect : '...',
failureRedirect : '/...'
})
);

Using dynamic callback URLs is necessary for situations where authentication is done on a backend server with auth requests being proxied to it by a number of web servers, not a single one. Or when multiple applications are hosted on a single Web server.

Is this strategy a singleton?

I'm using Gluu IDP and it uses passport for social login. It comes out of the box with strategies for popular social sites (not strictly OIDC). I set up an external OIDC provider using this library and it's working. I tried to set up a couple of others but if I enable a second OIDC provider, it seems to hijack the first one as well. Providers not using this strategy seem to coexist fine. I backed off to just one OIDC provider cause I'm demoing tomorrow, so I haven't mapped out the full scope. Is it expected that I can support multiple instances of this strategy configured for different providers? If so, then the fault may be with Gluu.

Documentation needs improvement.

I think the documentation for this strategy can use more content, especially given how new this is and how little information / tutorials are available out there.

InternalOAuthError: failed to obtain access token passport-openidconnect

File name : passport-openidconnect\lib\strategy.js
Line number : 93
if (err) { self.error(new InternalOAuthError('failed to obtain access token', err) ) ;

the error is logged in the console. But it does not a failureRedirect for some reason.

on the browser it just display as below
image
My https is not valid though.

It should redirect to failure redirect url automatically.

So as quick fix, I am doing below.
if (err) {
self.error(new InternalOAuthError('failed to obtain access token', err))
return self.fail(err);
}

Does not work with passport 0.3.0

I was trying to get this working alongside passport 0.3.0 (the latest version at the time), using express-session. However, I encountered an issue where passport.deserializeUser was never called to re-saturate the user. Reverting to passport 0.1.18 (the version on which this package depends) solved the problem.

Would be good to see this provider updated. Thanks for all your efforts!

Proxy issue on OAuth2 - ENETUNREACH failed to obtain access token

I have added below proxy options referred at - #jaredhanson/passport-oauth2#59

const agent = new HttpsProxyAgent(process.env.HTTP_PROXY); gStrategy._oauth2.setAgent(agent); passport.use(gStrategy);

but its not working, so directly added proxy on node_modules/oauth/lib/oauth2.js for workaround.

var queryStr= querystring.stringify(parsedUrl.query);
if( queryStr ) queryStr= "?" + queryStr;
httpsProxyAgent = new HttpsProxyAgent(process.env.HTTP_PROXY)
var options = {
host:parsedUrl.hostname,
port: parsedUrl.port,
path: parsedUrl.pathname + queryStr,
method: method,
headers: realHeaders
};
options.agent = httpsProxyAgent;
this._executeRequest( http_library, options, post_body, callback );
}

Any permanent fix is available? Every time we cant change the node_modules inside the Docker container. Kindly provide fixes.

Param is not defined when use_strict is on

Getting error in two files when using 'use_strict' (version "0.0.2").

Error files:
/passport-openidconnect/lib/strategy.js line 318
/passport-openidconnect/lib/state/session.js line 45

These loops should be updated to add 'const'

Could you please update that

I can't get this to work because self._passport.session is undefined

Is this maybe incompatible with a more recent passport version?
The code in this repo (snippet of req.login)

    this._passport.instance.serializeUser(user, this, function(err, obj) {
      if (err) { self[property] = null; return done(err); }
      self._passport.session.user = obj;
      done();
    });

whereas the same kind of code (req.login) inside of passport lib/http/request.js

    this._passport.instance.serializeUser(user, this, function(err, obj) {
      if (err) { self[property] = null; return done(err); }
      if (!self._passport.session) {
        self._passport.session = {};
      }
      self._passport.session.user = obj;
      if (!self.session) {
        self.session = {};
      }
      self.session[self._passport.instance._key] = self._passport.session;
      done();
    });

Also why does this module have it's own req.login implementation?
Not sure how to get past this.

CallbackURL gets called but no passport callbacks are being called

Any idea why my passport callback or my serializer/deserailizer are not being called at all? My provider is authenticating the user and sends a token back to my callback. I did change it to use form_post.

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser(function (user, done) {
    console.log('in serialize');
        done(null, user);
});

passport.deserializeUser(function (user, done) {
    console.log('in de-serialize');
    done(null, user);
});

passport.use(new OidcStrategy({
    authorizationURL: 'https://localhost:44316/identity/connect/authorize',
    tokenURL: 'https://localhost:44316/identity/connect/token',
    userInfoURL: 'https://localhost:44316/identity/connect/userinfo',
    clientID: 'mvc',
    clientSecret: 'secret',
    callbackURL: '/callback',
    responseType: 'id_token',
    scope: ['profile']
}, function (iss, sub, profile, done) {
    console.log('In callback 1');
    console.log(profile);
}));

The passport.use callback never gets invoked.

Unable to verify authorization request state. when I hit the auth routes by redirecting from a page but when I try again by redirecting to auth route from the page the auth works successfully

We only redirect from the page when we have no user in the session

` router.get('/auth/openidconnect',oidcSettings, oidcProviderReq);
router.get('/auth/openidconnect/callback',oidcSettings, oidcCallback);

let oidcSettings = function (req, res, next) {

  //provider contains all the required data

    var OidcStrategy = require('passport-openidconnect').Strategy;
    passport.use('oidc', new OidcStrategy({
        issuer: provider.settings.issuer,
        authorizationURL: provider.settings.authorizationURL,
        tokenURL: provider.settings.tokenURL,
        userInfoURL: provider.settings.userInfoURL,
        clientID: provider.settings.ClientID,
        clientSecret: provider.settings.clientSecret,
        callbackURL: provider.settings.callbackURL, 
        scope: 'openid profile'
    }, (issuer, sub, profile, accessToken, refreshToken, done) => {
        if (!(profile && profile._json && profile._json.email)) {
            return done(null, false);
        }
        req.params.provider =profile.id
        oidcLogin(req, profile, 'oidc_user', done); //basically either logs into the application or creates a new user 
    }));
    next();

}

let oidcProviderReq = function(req, res, next){
passport.authenticate('oidc', {scope: 'openid profile'})(req, res, next);
}

let oidcCallback = function(req, res, next){
passport.authenticate('oidc', function (err, user, info) {
if(err) throw err;
console.log(user)
})(req, res, next);
}

`

[Question/Feature Request] Allow to pass additional custom function for parsing UserInfo

Im using passport-openidconnect with Authelia.
With current implementation, only well defined list of UserInfo data (https://github.com/jaredhanson/passport-openidconnect/blob/master/lib/profile.js) can be passed to verify function.

It would be nice to be able pass additional parsing function from Strategy options.

It can work like this:

new OpenIDConnectStrategy({
  ...,
  customParse: function(profile, json){
    if (json.groups) { profile.groups = json.groups; }
  }
})
            var profile = Profile.parse(json);
            if (typeof options.customParse === 'function') {
                options.customParse(profile, json)
            }
            loaded(profile, json, body);

This way passport-openidconnect will allow users to parse any UserInfo. If this can be already achieved somehow, can you please clarify how?

(Sorry for my pure JS code example ;))

Compatibility with cookie-session

I'm looking at using this with a GraphQL service that we're hoping can remain completely stateless. We included the cookie-session package to put the authenticated OIDC tokens into the client cookies. There is an unfortunate interaction where it seems this passport strategy is setting some secrets in the session.

{
  "regularSessionKey": "regularSessionValue",
  "openidconnect:openid-connect": {
    "state": {
      "handle": "1ds+QByb7tO+p2zkV50WaqA4",
      "issuer": "",
      "authorizationURL": "",
      "tokenURL": "",
      "userInfoURL": "",
      "clientID": "",
      "clientSecret": "",
      "callbackURL": "",
      "params": {
        "response_type": "code",
        "client_id": "",
        "redirect_uri": "http://localhost:8080/oauth/callback",
        "scope": "openid extra",
        "state": "1ds+QByb7tO+p2zkV50WaqA4"
      }
    }
  }
}

Why does the strategy need to store so much in the session? All of the state keys except params.scope, handle, params.state (which are the same) are passed in when I construct new Strategy().

Since sending the secret with every client cookie is not an option, should that be interpreted as a clear indication that the passport-openidconnect requires a server-side session store? If so, could this be documented somewhere?

Doesn't return all data from user data endpoint

I'm currently using passport-openidconnect for PixelPin but the user data doesn't seem to return all the user when i ask for it using all the available scopes. It seems the JSON returned from the endpoint is restricted to email, email_verified, sub, nickname, given_name, family_name and birthdate(which returns incorrectly). I've used the PixelPin endpoint for Magento 2 and it returns all the data correctly so there has to be something wrong with passport-openidconnect.

Specific parameter for getting access token ?

I wanna use your clean and nice code in my project. but i have a critical issue about that. I want to pass specific data for getting access token. for example i wanna pass new code that generated from client id and client secret. How i can add that ?

curl -k -s -v -H "Content-Type: application/x-www-form-urlencoded" -H "Authorization: Basic b1BwcEJ5S0IwcXVPOjA3OGQ4MmQzZmVhYTQ1YzI5YmM3YTYxYTBmYWI1OTc5" -X POST 'https://localhost:5050/token' -d 'grant_type=authorization_code&code=798e589b5d4d4859b5a071cb6f3c6526&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb'

Support for audience

I cannot find support for specifying audience or am I missing something?
Do you have plans to include audience

Regards Joacim

oidc discovery well-known

Hi,
I looked to configure oidc auth with discovery/dynamic config.
I have the URL https://xxxxx/sp/.well-known/openid-configuration for that.

Here is my test :

const OidcStrategy = require('passport-openidconnect').Strategy;
passport.use('oidc', new OidcStrategy({
  issuer: "https://xxxxxx/sp",
  clientID: 'xxxx',
  clientSecret: 'xxxx',
  callbackURL: 'https://localhost:3000/authorization-code/callback',
  scope: 'openid profile'
}, (issuer, sub, profile, accessToken, refreshToken, done) => {
        console.log(profile);
  return done(null, profile);
}));

But this error occured :

TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received undefined
    at validateString (internal/validators.js:117:11)
    at Url.parse (url.js:159:3)
    at Object.urlParse [as parse] (url.js:154:13)
    at new Strategy (/tmp/myapp/node_modules/passport-openidconnect/lib/strategy.js:40:60)
    at Object.<anonymous> (/tmp/myapp/app.js:21:22)

Do you have an idea or a working example ?

Thanks

Typescript types package

Do you know if anyone is working on a types definition for the DefinitelyTyped repo? If not I could take a stab at starting it. I imagine it could largely be based on the one for the oauth2 strategy?

Project status

The last commit was 4 years ago, there are 25 open issues, some of which are security related, and 24 pull requests pending.

Is this project dead? Or perhaps the code is just basically done?

Maybe it's time to add a new maintainer?

I'm surprised that it isn't more widely used, since it seems to be the recommended package for openidconnect. Maybe I am missing something?

Proxy issue - Is it possible to expose the _oauth2 property, similar to the passport-oauth2 strategy?

I am trying to perform openid authentication behind a corporate proxy, and for that, I need to set the proxy options for the agent, similar to the following:

var HttpsProxyAgent = require('https-proxy-agent');
if (process.env['https_proxy']) {
 var httpsProxyAgent = new HttpsProxyAgent(process.env['https_proxy']);
 strategy._oauth2.setAgent(httpsProxyAgent);
}
passport.use(strategy);

I cannot perform this unless the ._oauth2 property is exposed.
Or is there any other way to configure the proxy options?

Issue with Authorization Code Flow

I'm using passport-openidconnet

File:/passport-openidconnect/lib/strategy.js
Line: 79:25
AuthorizationError: Missing parameter, 'code_challenge'

Your package is pretty much there in supporting this workflow by defining the necessary additional parameters like e.g. nonce, code_challenge, code_challenge_method using the authorizationParams function. However, I haven't seen an option to extend the authentication request by similar means, e.g. with the necessary parameter code_verifier.
Did I miss something? If not it would be great you could add a similar mechanism like the authorizationParams to the authentication request

Here is my detail error message:
AuthorizationError: Missing parameter, 'code_challenge'

at Strategy.authenticate (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/passport-openidconnect/lib/strategy.js:79:25)
at attempt (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/passport/lib/middleware/authenticate.js:367:16)
at authenticate (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/passport/lib/middleware/authenticate.js:368:7)
at Layer.handle [as handle_request] (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/layer.js:95:5)
at /Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/index.js:335:12)
at next (/Users/michael/Desktop/working/Gitlab/covid-more/node_modules/express/lib/router/index.js:275:10) {

code: 'invalid_request',
uri: undefined,
status: 500
}

Release new version

Like I said in issue #2 I'm interested in releasing a new version of this strategy (and I guess other users will be too). This include dedicating the time needed for testing and release.

But it would be nice to have info from the maintainers:

  • do you plan for a new milestone ?
  • are there new functionalities from the last release that require new tests ?

Thanks.

Support of PKCE workflow

Some OpenId Connect based Server Support the PKCE workflow according to [https://tools.ietf.org/html/rfc7636#page-8].
Your package is pretty much there in supporting this workflow by defining the necessary additional parameters like e.g. nonce, code_challenge, code_challenge_method using the authorizationParams function. However, I haven't seen an option to extend the authentication request by similar means, e.g. with the necessary parameter code_verifier.
Did I miss something? If not it would be great you could add a similar mechanism like the authorizationParams to the authentication request

All parameters of OpenIDConnectStrategy are not given in the README.md documentation

Thanks for this nice passport library. I just used it and was blocked during some time, because I was not understanding why I couldn't get the email and displayName from a lemonldap-ng server which was configured for sending them in the claims. Finally, in looking in the examples (that are linked to in the github README.md but not on the passport-openidconnect page), I saw that there was a scope argument for the openIDConnectStrategy. Then I added scope: ['email', 'profile'] in the object provided to OpenIdStrategy and voilà ! it worked.
So I think that all arguments of the OpenIdStrategy should be listed in a paragraph in the README.md file and for the poor programmer. That said, now, it works, so thanks a lot !

Sending specific state while calling passport.authenticate

Hi All,

I am sending a particular state parameter with the authenticate call as below. But that state is changed to a random string. How do I send a specific state and retrieve it after the callback url is called. Basically what I want is, I have couple of parameters based on which I will redirect to different routes. those i am trying to pass as state parameters, but they are changed to some random string and they are lost. How do I retrieve them. Thanks.

passport.authenticate('oidc', { state: JSON.stringify({ tab: 'placement' }) })

const passport = require('passport');
const OidcStrategy = require('passport-openidconnect').Strategy;

app.use(
session({
secret: crypto.randomBytes(64).toString('hex').substring(0, 20),
resave: true,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
passport.use(
'oidc',
new OidcStrategy(
{
issuer: 'xxxx',
authorizationURL: 'xxxx',
tokenURL: 'xxxx',
userInfoURL: 'xxxx',
clientID: 'xxxx',
clientSecret: 'xxxxx',
callbackURL: 'xxxxx',
scope: 'profile groups',
nonce: crypto
.randomBytes(64)
.toString('hex')
.substring(0, 20),
},
(issuer, sub, profile, accessToken, refreshToken, params, done) => {

  return done(null, profile);
}

)
);
app.use('/login',passport.authenticate('oidc', { state: JSON.stringify({ tab: 'placement' }) }) )`

Provide an option to authenticate using header for testing

I have a situation where I am logging in using a username and password using Auth0. I would like to be able to use the access token I get without a browser (testing uses supertest). I tried using JWT as an alternative strategy alongside this one but having other issues.

Would it be possible to add the Authorization header as a way to log in for testing?

setting skipUserProfile option false throws exception

line 191 strategy.js calls

_self.verify(req, iss, sub, profile, verified);

which apparently results in a call to oauth2.js with incorrect parameters ultimately failing on

profile.id

because profile is undefined

REST API middleware support

I can see your examples mostly used on express sessions middleware part. There is any option on without sessions, bcz we developed api endpoints. So no option for maintain sessions in api request. This passport-openidconnect module is suitable for REST API development?

Any one help me!!

Thanks in advance

Token validation missing

We have seen strategy.js file, in that it showing validation claims part is TODO. When can we expect that to be integrated?

We have couple of other questions

  1. what is the difference between this repository(passport-openidconnect) and passport-openid both are authored by @jaredhanson

npm package is not up to date with repo

I'm trying to use the auth strategy on a project and take advantage of discovery. It looks like I should be using the .config method, but this is not available based on the most recently npm published module.

If the code is stable, can you version bump and publish the package? Thank you - I really appreciate passport and the various strategies you support!

Unable to change Response type to id_token

I am trying to change the response type to id_token from code, but it not changing.

I checked the codebase, the params.response_type is statically written code in lib/strategy.js

Some of the providers, Don't support response type code

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.