Giter VIP home page Giter VIP logo

oauth2's People

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

oauth2's Issues

resuming flow after redirect

Hi, I'm having difficulty implementing facebook authentication with this library.

After I create an instance of AuthorizationCodeGrant I then redirect the users to the .getAuthorizationUrl(). When they eventually land back on my app I need call .handleAuthorizationResponse() on the grant object. But as the app has reinitialised I have to recreate the grant object and this isn’t working, I think because it’s not the same grant object that generated the redirect url? Do I need to serialize and store the original grant object for when the user returns back?

The documentation shows this:

  // `redirect` is an imaginary function that redirects the resource
  // owner's browser.
  await redirect(grant.getAuthorizationUrl(redirectUrl));

  // Another imaginary function that listens for a request to `redirectUrl`.
  var request = await listen(redirectUrl);

I’m not sure how I could implement these imaginary methods so I’m redirecting the user (in the current window) and when they return I’m trying restore state so I can continue. Is there a better way to do this?

Thanks

oauth2 package - pass in scope delimiter character, default to 'a single space

Originally opened as dart-lang/sdk#20418

This issue was originally filed by [email protected]


when passing in a list of scopes to get access to for a user the code currently has a hard coded scope delimiter:

      if (!scopes.isEmpty) fields["scope"] = scopes.join(' ');

would it be possible to pass in a delimiter character, as I understand it facebook uses a comma rather than a space, so I don't think it is possible to use the oauth2 package to connect with facebook for this reason.

Client credentials grant

Hello!
Is there any plan to include the client credentials grant into this package at some point? It would be really helpful in order to continue using one package for all oauth2 requirements, and considering an implementation of client credentials has not yet been done for Flutter.

State parameter could be optional

I understand that the state parameter is recommended and is good for security, but I have come across certain APIs that don't expect the state parameter, so they don't return it on the redirect, causing the auth flow to break. Would you be open to having it be optional, similar to enablePKCE? I'd be happy to make the changes and open a pull request, as I'm already using a local modified copy with these changes.

Authorization Code PKCE Support

Unless I am mistaken, I haven't seen any support for Authorization Code with PKCE. Is there any chance we see such support in the future? However, if it is already implemented, how do you use it?

Thanks!

TypeError on failed auth response

Attempting a client.get with known bad tokens, I see the following error:

type 'List<dynamic>' is not a subtype of type 'List<AuthenticationChallenge>' where
I/flutter (21237):   List is from dart:core
I/flutter (21237):   List is from dart:core
I/flutter (21237):   AuthenticationChallenge is from package:http_parser/src/authentication_challenge.dart
I
I/flutter (21237): #0      AuthenticationChallenge.parseHeader (package:http_parser/src/authentication_challenge.dart:37:12)
I/flutter (21237): #1      Client.send (package:oauth2/src/client.dart:117:12)
I/flutter (21237): <asynchronous suspension>
I/flutter (21237): #2      BaseClient._sendUnstreamed (package:http/src/base_client.dart:171:38)
I/flutter (21237): <asynchronous suspension>
I/flutter (21237): #3      BaseClient.get (package:http/src/base_client.dart:34:5)

Flutter Doctor

[✓] Flutter (Channel beta, v0.3.1, on Mac OS X 10.12.6 16G1314, locale en-US)
• Flutter version 0.3.1 at /Users/tony/afero/flutter
• Framework revision 12bbaba9ae (12 days ago), 2018-04-19 23:36:15 -0700
• Engine revision 09d05a3891
• Dart version 2.0.0-dev.48.0.flutter-fe606f890b

[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
• Android SDK at /Users/tony/Library/Android/sdk
• Android NDK at /Users/tony/Library/Android/sdk/ndk-bundle
• Platform android-27, build-tools 27.0.3
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
• All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 9.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 9.2, Build version 9C40b
• ios-deploy 1.9.2
• CocoaPods version 1.4.0

[✓] Android Studio (version 3.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 24.0.1
• Dart plugin version 173.4700
• Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)

[✓] Connected devices (1 available)
• Android SDK built for x86 • emulator-5554 • android-x86 • Android 8.0.0 (API 26) (emulator)

• No issues found!

Resource Owner Password Grant #

Hi, is this package supposed to work with aqueduct?
using this snippet, i get 200 on my aqueduct for both points /auth/token and http://localhost:8888/articles

but i do not know how to read the response back, tried print('$client');, i know that is wrong, because it did not work for me;
in aqueduct we could do sth like this to protect an endpoint

.route("/articles/[:id]")
        .link(() => Authorizer.bearer(authServer))
        .link(() => ArticlesController(context));

so is it meant to work with aqueduct, and how would i get the response body.
Thank you.

// This URL is an endpoint that's provided by the authorization server. It's
// usually included in the server's documentation of its OAuth2 API.
final authorizationEndpoint =
    Uri.parse("http://localhost:8888/auth/token");

// The user should supply their own username and password.
final username = "example user";
final password = "example password";

// The authorization server may issue each client a separate client
// identifier and secret, which allows the server to tell which client
// is accessing it. Some servers may also have an anonymous
// identifier/secret pair that any client may use.
//
// Some servers don't require the client to authenticate itself, in which case
// these should be omitted.
final identifier = "my client identifier";
final secret = "my client secret";

// Make a request to the authorization endpoint that will produce the fully
// authenticated Client.
var client = await oauth2.resourceOwnerPasswordGrant(
    authorizationEndpoint, username, password,
    identifier: identifier, secret: secret);

// Once you have the client, you can use it just like any other HTTP client.
var result = await client.read("http://localhost:8888/articles");

Ready for production usage?

Hi thanks for the foundational library! I wonder whether it is mature enough to be used in production environment? Thanks!

Exposes the raw `expiresIn` value in the Credentials class

The expiresIn received from the server is transformed into a convenient DateTime. It would be nice to expose the initial int value as well.

It would improve interoperability with other libs like Fresh.

For now I'm doing the inverse computation to convert a Credentials instance to a fresh token:

OAuth2Token(
  accessToken: credentials.accessToken,
  refreshToken: credentials.refreshToken,
  expiresIn: credentials.expiration.difference(DateTime.now()).inSeconds,
)

code_challenge_method

Hello I would like to add option to use "plain" in code challenge method because my zoom api says.
Code challenge method is not supported when I want to use S256.
Something like the following.
I have already tested with code locally downloaded and changed.
It works ok.

Thank you in advance.

Uri getAuthorizationUrl(Uri redirect,
{Iterable scopes, String state, bool s256 = true }) {
if (_state != _State.initial) {
throw StateError('The authorization URL has already been generated.');
}
_state = _State.awaitingResponse;

if (scopes == null) {
  scopes = [];
} else {
  scopes = scopes.toList();
}

_codeVerifier = _createCodeVerifier();
var codeChallenge = s256 ? base64Url
    .encode(sha256.convert(ascii.encode(_codeVerifier)).bytes)
    .replaceAll('=', '') : _codeVerifier;

_redirectEndpoint = redirect;
_scopes = scopes;
_stateString = state;
var parameters = {
  'response_type': 'code',
  'client_id': identifier,
  'redirect_uri': redirect.toString(),
  'code_challenge': codeChallenge,
  'code_challenge_method': s256 ? 'S256' : 'plain'
};

if (state != null) parameters['state'] = state;
if (scopes.isNotEmpty) parameters['scope'] = scopes.join(_delimiter);

return addQueryParameters(authorizationEndpoint, parameters);

}

oauth2 library needs updating on pub.dartlang.org

Originally opened as dart-lang/sdk#15809

This issue was originally filed by [email protected]


The current version of the oauth2 package on pub.dartlang.org is not compatible with changes made to the http package.

In order to make oauth2 work, it was necessary to use the bleeding edge source code for the oauth2 package. The bleeding edge oauth2 package needs to be pushed to pub and the version number incremented (the source on pub differs from the bleeding edge - even though they have the same version number).
 

See https://groups.google.com/a/dartlang.org/forum/?fromgroups=#!topic/misc/VJDXd5aT2HM
for more details.

More generally - the process to manage and update packages that are part of the dart source distribution needs to be improved. Perhaps consideration should be given to making each of these packages a separate project on github? It is currently difficult to track down the source code that corresponds to a specific release of an SDK bundled package.

OAuth2 session logout

Hi,

in my application I am using the Password Owner Credential Grant in combination with Keycloak as authentication server. The authentication and token based communication works like a charm with the OAuth2 Client. Unfortunately, I am running into difficulties when it comes to the user session logout.

Keycloak's discovery endpoint gives us an URL like .../auth/realms/master/protocol/openid-connect/logout as end_session_endpoint.

Now, when I send a POST-Request to the above mentioned endpoint with the use of the client I receive the following response: "error":"unauthorized_client","error_description":"INVALID_CREDENTIALS: Invalid client credentials"

Researching the error message resulted in an interesting stack overflow post
It says that you have to add the client_id to your request when working with public clients.

Since the OAuth2-Package is using the client_id as identifier could you add a method to support the logout functionality?

Credentials.fromJson doesn't support underscored keys

I don't know the OAuth2 standard, but I seem to find a lot of providers that use underscores in their JSON instead of camel casing.

The Credentials.fromJson constructor expects camel casing and doesn't recognize the underscored counterparts.

Is this intended behaviour?

Change the value of basicAuth

Is there any methods that can change the boolean value of basicAuth in AuthorizationCodeGrant().
I am using an OAuth service that does not support basic auth.

oauth2: Add text/javascript as a possible response content-type when validate token

Originally opened as dart-lang/sdk#17067

This issue was originally filed by [email protected]


https://codereview.chromium.org/177093006

Some api providers like dropbox (for example /token endpoint) set content-type response to text/javascript so _validate call fail.

Unhandled exception:
FormatException: Invalid OAuth response for "https://api.dropbox.com/1/oauth2/token": content-type was "text/javascript", expected "application/json".

Response is {"access_token": "TOKEN", "token_type": "bearer", "uid": "UID"}

Basic Auth encodes ascii characters

I will make this as simple as possible.

in method resourceOwnerPasswordGrant
given basicAuth value is true by default (which is the right behavior)
the method generates a basicAuth of the provided identifier and secret via a method called basicAuthHeader

given identifier is test and secret is test^ (^ is a valid ascii character)
basicAuthHeader(identifier, secret)

expected result Basic dGVzdDp0ZXN0Xg== or Basic dGVzdDp0ZXN0Xg
actual result Basic dGVzdDp0ZXN0JTVF

which causes an authentication failure.

here is what the method does

String basicAuthHeader(String identifier, String secret) {
  var userPass = Uri.encodeFull(identifier) + ':' + Uri.encodeFull(secret);
  return 'Basic ' + base64Encode(ascii.encode(userPass));
}

Conflicting method names in README

Unless I'm mistaken, the sample code in the README defines Future<oauth2.Client> getClient() async but calls var client = await loadClient();.

Custom parameters

Is it possible to read the http response after authentication ?
I would like to get customs parameters and i can't with
await ouath2.resourceOwnerPasswordGrant(Uri.parse('${_url}/oauth2/token'), _username,_password, identifier: null, secret: null);

Sample to get global_user_id parameter with my c# code
` Client = new RestClient(url);
IRestRequest request = new RestRequest("oauth2/token", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddParameter("grant_type", "password");
request.AddParameter("username", username);
request.AddParameter("password", password);

        IRestResponse response = new RestResponse();
        response = Client.Execute(request);
        if (response.StatusCode == System.Net.HttpStatusCode.OK)
        {
            string json = response.Content;
            Dictionary<string, Object> dictio = JsonConvert.DeserializeObject<Dictionary<string, Object>>(json);
            Token = dictio["access_token"].ToString();
            currentUser = getGlobalUser((long)dictio["global_user_id"]);`

How to logout?

Can I generate correct logout url somehow? Or I need to do it manually?

PasswordGrant Support keycloak?

In example use authorizationEndpoint

final authorizationEndpoint =
    Uri.parse("https://keycloak-dev.xxx.com/auth/realms/xxx/protocol/openid-connect/auth")

but keycloak Password Grant use tokenEndpont URL

And I use authorizationEndpoint get errors below

Unhandled exception:
NoSuchMethodError: The getter 'length' was called on null.
Receiver: null
Tried calling: length
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1      _Uri._uriEncode (dart:core-patch/uri_patch.dart:44:23)
#2      Uri.encodeFull (dart:core/uri.dart:1148:17)
#3      basicAuthHeader (package:oauth2/src/utils.dart:13:57)
#4      resourceOwnerPasswordGrant (package:oauth2/src/resource_owner_password_grant.dart:71:34)
<asynchronous suspension>

dart http incompatability

Because every version of flutter_driver from sdk depends on http 0.12.0 and oauth2 1.2.2 depends on http ^0.11.0, flutter_driver from sdk is incompatible with oauth2 1.2.2.
And because no versions of oauth2 match >1.2.2 <2.0.0, flutter_driver from sdk is incompatible with oauth2 ^1.2.2.

is it possible to update the pubspec so I can update to latest flutter version?

Need refreshTokenEndpoint params.

Our internal oauth2 refresh_token api address is not the tokenEndpoint, but i cannot specify the address through the oauth2 package. Can we add a params like refreshTokenEndpoint or is there any other way to achieve my needs?

Thanks!

Extend OAuth2 package to support OpenID connect

Originally opened as dart-lang/sdk#15248

This issue was originally filed by [email protected]


After thinking this through, I realize this is a fairly major feature request.

The current OAuth2 package (http://pub.dartlang.org/packages/oauth2)

does not support OpenID connect. For example, Openid connect returns a id_token as part of the authorization flow.

A small enhancement would be to extend Credentials.dart to provide the raw value of id_token if it is present.

Ideally, support would be provided for JSON web tokens, signature verification, etc.

Concurrent refreshCredentials issue

refreshCredentials in https://github.com/dart-lang/oauth2/blob/master/lib/src/client.dart#L148 has concurrent issue , assume we have an expired access token and call client.read twice , refreshCredentials refreshed access token twice and in many OAuth server implementation , if you get access token and refresh it again , first access token will revoked (You can have only one valid access token)

We need some lock mechanism like https://pub.dev/packages/synchronized

Flutter example

I have tried following the comments on #31

However, it´s not completed and I´m to new to Flutter and Dart to be able to get this to work.

Is there anyone who can create a more complete example?
Would be much appreciated.

Thank you

oauth2 package: add option to restrict the access only to users with google two factor auth enabled

<img src="https://avatars.githubusercontent.com/u/713559?v=3" align="left" width="96" height="96"hspace="10"> Issue by Emasoft
Originally opened as dart-lang/sdk#20420


PROBLEM: For security reasons there is often the need to restrict the access to a web app only to people with google two factor authentication enabled.

SOLUTION: Add to the oauth2 dart library an option to restrict the access only to users with google two factor auth enabled. This restriction should work with all components, including Google+ Sign-In and OpenID Connect.

Possibility to send custom header for 'password' grant type

I need to append one header during authentication via 'password' grant type

var client = await oauth2.resourceOwnerPasswordGrant(
authorizationEndpoint, username, password,
identifier: identifier, secret: secret);

But, I can not see a way to do this with resourceOwnerPasswordGrant

Can you please, provide possibility to do this

Using with Chrome

Hi, the plugin is working perfectly with iOS and Android.
I was running my app under web develop mode, with Chrome, but I have 1 error calling:

var client = await oauth2.resourceOwnerPasswordGrant
        authorizationEndpoint, username, password,
        identifier: identifier, secret: secret, basicAuth: false);

Error:
Error: XMLHttpRequest error.
package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 248:20 get current
package:http/src/browser_client.dart 84:22
package:dart-sdk/lib/async/zone.dart 1381:54 runUnary
package:dart-sdk/lib/async/future_impl.dart 140:18 handleValue
package:dart-sdk/lib/async/future_impl.dart 682:44 handleValueCallback
package:dart-sdk/lib/async/future_impl.dart 711:32 _propagateToListeners
package:dart-sdk/lib/async/future_impl.dart 516:7 [_complete]
package:dart-sdk/lib/async/stream_pipe.dart 65:11 _cancelAndValue
package:dart-sdk/lib/async/stream.dart 1253:11
package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 326:14 _checkAndCall
package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 331:39 dcall
package:dart-sdk/lib/html/dart2js/html_dart2js.dart 35657:58 .......

Thanks for your help.

Using with session

Can we use oauth2 with session?
I need to keep user connected, then disconnect them after a while of inactivity

Invalid client secret when refreshing token for Microsoft Graph API.

I had a problem using this library with the Microsoft Graph API.
This might be a corner case because during development I constructed the credentials.json myself (using values previously generated via postman).

  1. I loaded the manually built credentials using new oauth2.Credentials.fromJson().
  2. I executed requests against the Graph API which was working fine.
  3. After the expiration time of the token, the refresh process failed with: AADSTS50012: Invalid client secret is provided.

After some digging, I found that it seemed to be connected to client secret encoding for the auth header.
I experimented and changed function basicAuthHeader in utils from:

String basicAuthHeader(String identifier, String secret) { var userPass = Uri.encodeFull(identifier) + ":" + **Uri.encodeFull**(secret); return "Basic " + base64Encode(ascii.encode(userPass)); }

to

String basicAuthHeader(String identifier, String secret) { var userPass = Uri.encodeFull(identifier) + ":" + **Uri.encodeComponent**(secret); return "Basic " + base64Encode(ascii.encode(userPass)); }

This fixed my problem.
(However I am not sure if this has any side effects, therefore I will not create a Pull request for this)

Password authentication exception.

Update: Happens only if there is a scope parameter present.

Exception thrown on line:

var credentials = await handleAccessTokenResponse(
response, authorizationEndpoint, startTime, scopes, delimiter,
getParameters: getParameters);

type '_CompactLinkedHashSet' is not a subtype of type 'List'

Response appears to be as expected:

String jsonStr = await response.body;
print(jsonStr):

{"access_token":"670d5dac-54a8-215a-8c3a-b13e1eff72bb","token_type":"bearer","expires_in":40718,"scope":"read_profile"}


Future<Client> resourceOwnerPasswordGrant(
    Uri authorizationEndpoint, String username, String password,
    {String identifier,
    String secret,
    Iterable<String> scopes,
    bool basicAuth = true,
    CredentialsRefreshedCallback onCredentialsRefreshed,
    http.Client httpClient,
    String delimiter,
    Map<String, dynamic> getParameters(
        MediaType contentType, String body)}) async {
  delimiter ??= ' ';
  var startTime = new DateTime.now();

  var body = {
    "grant_type": "password",
    "username": username,
    "password": password
  };

  var headers = <String, String>{};

  if (identifier != null) {
    if (basicAuth) {
      headers['Authorization'] = basicAuthHeader(identifier, secret);
    } else {
      body['client_id'] = identifier;
      if (secret != null) body['client_secret'] = secret;
    }
  }

  if (scopes != null && scopes.isNotEmpty)
    body['scope'] = scopes.join(delimiter);

  if (httpClient == null) httpClient = new http.Client();
  var response = await httpClient.post(authorizationEndpoint,
      headers: headers, body: body);
  String jsonStr = await response.body;
  print(jsonStr);

  var credentials = await handleAccessTokenResponse(
      response, authorizationEndpoint, startTime, scopes, delimiter,
      getParameters: getParameters);
  return new Client(credentials,
      identifier: identifier,
      secret: secret,
      httpClient: httpClient,
      onCredentialsRefreshed: onCredentialsRefreshed);
}

resourceOwnerPasswordGrant doesn't support a different tokenEndpoint

Presently resourceOwnerPasswordGrant will save the authorizationEndpoint as the tokenEndpoint in the saved credentials and doesn't allow for a unique endpoint for auth vs tokens. Is this intended or a side-effect of reusing the exiting structure? Would you be open to a PR to allow an optional tokenEndpoint to be provided?

how to set timeout and connectTimeOut

how to set timeout and connectTimeOut。
i can found where can set time out and connect time out , now some request spends too many times to i can't wait the response,
Looking forward to your answer
thanks ,very much

oauth2 0.3.1+1 still tries to resolve from relative path

<img src="https://avatars.githubusercontent.com/u/654526?v=3" align="left" width="96" height="96"hspace="10"> Issue by financeCoding
Originally opened as dart-lang/sdk#8081


the library does not use package: for imports of http.dart it uses relative path. On another note I've done all the necessary stuff to wire up this package in my own project, I dont think it fully works yet, which you may know already. If it does, are there any examples of something using it?

Allow more content types for authorization response

Right now, the authorization response is assumed to be always "application/json". But this makes it non-compliant with facebook's response.

On success:
returns "text/plain" with response in multipart form data like response.

On Failure:
returns "text/javascript" with Json object as response.

Is it ok, if i submit a pull request that handles this acoording to whats in the "content-type" of the response?

Add workaround for Facebook oauth bug to oauth2 package

<img src="https://avatars.githubusercontent.com/u/336447?v=3" align="left" width="96" height="96"hspace="10"> Issue by MaxHorstmann
Originally opened as dart-lang/sdk#12366


Facebook's oauth2 implementation has a bug. It returns the access token as plain text (text/plain) instead of json (application/json).

See e.g. http://stackoverflow.com/questions/3862108/facebook-oauth-access-token-missing

Unforunately, this breaks the oauth2 package (http://pub.dartlang.org/packages/oauth2) right here: https://code.google.com/p/dart/codesearch#dart/trunk/dart/pkg/oauth2/lib/src/handle_access_token_response.dart&amp;l=37

Ideally Faceboook should fix this return json like the oauth2 spec says, but well, so far they haven't done so.

Since Facebook sign-in is a fairly common use case, my suggestion is to add some flexibility here and handle both a json or plaintext response. The plaintext response string looks like this:

access_token=CAAC9nzmHiUwBAE36sC6fPvDOtlZAFGfoLEfZAcfS2VnEOyo7ZCvckG55tCvzwRQNuSl2unMpFYxxxxxdostdNU38grYyEVSIUe2MhIWXII0ufc380vUc56B6cYAtli153PKuEZA1BT44AoyrtQTc3UT6meZAiO1YZD&expires=5181866

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.