Giter Site home page Giter Site logo

yiisoft / yii2-authclient Goto Github PK

View Code? Open in Web Editor NEW
464.0 47.0 245.0 725 KB

Yii 2 authclient extension.

Home Page: http://www.yiiframework.com

License: BSD 3-Clause "New" or "Revised" License

PHP 98.42% CSS 0.35% JavaScript 0.90% Makefile 0.33%
php yii2 oauth facebook twitter vk github google linkedin hacktoberfest

yii2-authclient's Introduction

AuthClient Extension for Yii 2


This extension adds OpenID, OAuth, OAuth2 and OpenId Connect consumers for the Yii framework 2.0.

For license information check the LICENSE-file.

Documentation is at docs/guide/README.md.

Latest Stable Version Total Downloads Build Status

Installation

The preferred way to install this extension is through composer.

Either run

composer require --prefer-dist yiisoft/yii2-authclient

or add

"yiisoft/yii2-authclient": "~2.2.0"

to the require section of your composer.json.

yii2-authclient's People

Contributors

albertborsos avatar alexgx avatar arhell avatar azmeuk avatar bizley avatar cebe avatar exileed avatar hirenbhut93 avatar kartik-v avatar klimov-paul avatar latinvm avatar lesha701 avatar lucianobaraglia avatar machour avatar marty-macfly avatar mtangoo avatar okiwan avatar pana1990 avatar qiangxue avatar rhertogh avatar samdark avatar shketkol avatar silverfire avatar slava-arapov avatar softark avatar sohelahmed7 avatar soisik avatar sonicgd avatar vistart avatar vkaylee 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  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

yii2-authclient's Issues

Add support for Client Credentials grant type

OAuth2 client now is working only with authorization_code grant, but there is another way of obtaining an access token: client_credentials grant (you can read here, for example).
So, to use this grant we need to extend OAuth2 class to change fetchAccessToken method, including it's signature (beacuse authCode is not used in this grant).
Why not add support of this common used grant to extension?

Twitter acount connect

Hello Everyone,

I'm trying to use Twitter oAuth and everything works until Twitter redirects back to my application. This is the error I receive:

Exception – yii\base\Exception

Request token is required to fetch access token!

1. in /var/www/app/vendor/yiisoft/yii2-authclient/OAuth1.php

 * @param array $params additional request params.
     * @return OAuthToken OAuth access token.
     * @throws Exception on failure.
     */
    public function fetchAccessToken(OAuthToken $requestToken = null, $oauthVerifier = null, array $params = [])
    {
        if (!is_object($requestToken)) {
            $requestToken = $this->getState('requestToken');
            if (!is_object($requestToken)) {
                throw new Exception('Request token is required to fetch access token!');

This occurs on line 124. Can anyone confirm this issue?

Hi I am not sure why the oath access tokena and oath access secret is tored in session

HI I want to use oauth access token and oauth acess secret which are stored in session

[yii\authclient\clients\Twitter_ef71f520786335688cd762d29aaa2ac98b6bd42f_token] => yii\authclient\OAuthToken Object
        (
            [tokenParamKey] => oauth_token
            [tokenSecretParamKey] => oauth_token_secret
            [createTimestamp] => 1447473086
            [_expireDurationParamKey:yii\authclient\OAuthToken:private] => 
            [_params:yii\authclient\OAuthToken:private] => Array
                (
                    [oauth_token] => 48575497-RTIItaMJBC5LrFl0I2TjYw0ihByC0QuRdRxf44tVX
                    [oauth_token_secret] => IcdvTgwiclWGNhX4TrsDjEkEdNwVF7l1XzXmgpNstGfkV
                    [user_id] => **********
                    [screen_name] => ***********
                    [x_auth_expires] => 0
                )

        )

I want to use oauth_token and oauth_token_secret param that is stored in session as object after user athenticate but they are stored in private values so I think we need them for further processing the request those values should be accessbile easily other wise I don't see any reason of storing them on session if we can't use. Suggestions and comment needed may be I am missing piece of cake.

thank you

Migration

Maybe move SQL code for generating auth table to migration?

suggestion to append documentation

Somewhere in your installation documentation you guys should mention that you need to add "auth" to the list of allowed actions in the rules, or else the widget just takes you in circles to your own site.

'actions' => [ 'login', 'error', 'auth' ],

Cannot upload a file to facebook

I tried to upload a file to a facebook page. Currently facebook allows two ways to do that: thought the URL of an image that's on the web; through a file upload.

The file upload requires multipart/form-data header, which is set if you add CURLFile object to the parameters of the request (or if you put '@' before the value of the param before PHP 5.6).

Currently this is not working. Even if I put CURLOPT_POSTFIELDS with CURLFile as a param, before sending the request through setCurlOptions, I am not able to upload a photo, because my parameters are overriden in composeRequestCurlOptions. I can override this method and change what needed, but I don't think my parameters should be overwritten by default.

My code:

$response = $this->facebook->api("$this->facebookPageId/photos", 'POST', [
   'source' => new \CURLFile($post->photo->mainFilepath),
   'caption' => $post->caption,
]);

Thanks for the plugin!

AuthAction: cannot get refresh_token with GoogleOAuth

Google will only send a refresh_token on the very first authorization and then never again. On any subsequent authorization only an id_token is sent which cannot be used to acquire a new access token once the old one has expired. This is a show-stopper when attempting to acquire the refresh token from users who have already been authorized in case something went wrong and the refresh token was not permanently stored. There are only two ways around this:

  • Ask your users to revoke access to your app in their Google account and try again (unrealistic), or
  • Sending an extra parameter approval_prompt to force. More info on the topic here.

Using the approval_prompt parameter is however currently unsupported by the GoogleOAuth client.

Twitter login getting email address of the user

Hi everyone!

I could successfully get emails of the user while logging in with google, facebook, and vkontakte.
Twitter by default doesno allow getting an email of the user.
After a request I got this permission and in my Twitter apps I have
Request email addresses from users as checked.

But in the result array I get a lot of data with twits, username, timezone, etc. except the email.
What can be the problem?

LinkedIn connections request returns access denied

I am using authClient to access linkedIn.

The scope being passed in 'scope' => 'r_fullprofile r_emailaddress r_contactinfo r_network'

This seems to request the right scope in the OAuth request.

however, when later issuing a $this->client->api('people/~/connections', 'GET');

I receive a

Request failed with code: 403, message:

403
1430882052185
D7N58EN2FU
0
Access to connections denied

Error.

i cannot determine if this is a linkedIn issue or a possible problem with authClient.

Any guidance would be appreciated

Не знаю как правильно сделать пулреквест

в файле clients/vkontakte нет возможности изменять поля, которые нужны для запроса у соцсети. предлагаю добавить свойство

public $userAttributes = 'uid,first_name,last_name,nickname,screen_name,sex,bdate,city,country,timezone,photo_max_orig,occupation,activities';

и его обработку

    /**
     * @inheritdoc
     */
    protected function initUserAttributes()
    {
        $response = $this->api('users.get.json', 'GET', [
            'fields' => $this->userAttributes
        ]);```

тогда сможем настраивать нужные поля )

problem with OAuth1 class

Some of web services seems to have more strict rules for getting the access token to access their services using Oauth1. They use the secret key received from the temporary token to create a key which is used as a part of the signature key to encrypt request for getting the access token. And despite there are some ambiguity in specification https://tools.ietf.org/html/rfc5849 they looks to be right in their solution.

This authorization code has been used.

I get this error when I am using facebook client to login.
This is the error I get.

Exception – yii\authclient\InvalidResponseException
Request failed with code: 400, message: {"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100,"fbtrace_id":"CKSTHLF8PgK"}}

I googled this issue and found that we cannot send request to get access token twice.

UnknownMethodException when used in console app

We have encountered a problem with our app when using the authclient (specifically LinkedIn) within a console app. Our use case is the following: we post messages to LinkedIn using a cron job. In order to do this, we save the user's auth token in the database and load it whenever needed.

When setting up LinkedIn within the console (before any message is actually posted), we use the following code:

$authClients = \Yii::$app->get('authClientCollection');
$linkedIn = $authClients->getClient('linkedin');
$linkedIn->setAccessToken([
    'params' => $authToken, // The $authToken parameter is coming from the database
                            // and it is in the correct format; this works in the web app
]);

The exception thrown is of type UnknownMethodException:

Calling unknown method: yii\console\Application::getSession()

It is thrown by the setAcessToken method, because internally it calls saveAccessToken, which in turn tries to retrieve the session from the app. Since console apps have no session, this call fails. We have tried to set up a session component for the console app, but this won't solve it either, because instead of using Yii::$app->session (which is resolved by Yii's magic methods) the code calls Yii::$app->getSession() which fails.

Please note that in our particular use case we never actually need to save the access token in the session, as we are not using the authentication flow in this scenario.

Change account on sign in

Is it possible on sign out to end the google session or to give the user the possibility to choose which account he wants?

What I'm trying to do is on every login to give the user the posibility to change the account that he wants to sign in. Can't find any functions to do this. Once the user logged in with an account, that's it. He doesn't have the option to choose another account.

Thanks!

Make using of refreshAccessToken optional

Some auth servers may not support refresh tokens. As said in RFC:

Issuing a refresh token is optional at the discretion of the authorization server.

So in this case we need to change refreshAccessToken method of OAuth2 class to not send such requests. Why not make this functionality optional (for example, check a config property in BaseOAuth::restoreAccessToken before trying to refresh token)?

POST data in json or xml format to api client (e.g. Linkedin)

I'm successfully authenticated using yii\authclient\clients\Linkedin
However the share endpoint on linkedin API requires a POST in XML or JSON (https://developer.linkedin.com/docs/share-on-linkedin)

$data = ['comment' => 'Check out developer.linkedin.com! http://linkd.in/1FC2PyG', 'visibility'=>['code'=>'anyone'] ];
try {
    $linkedin_response = $client->api('people/~/shares?format=json', 'POST', $data);
} catch(\Exception $ex) {
    error_log("Linkedin error posting message: " . var_export($ex->getMessage(), true));
}

I get the error:
Linkedin error posting message: 'Request failed with code: 400, message: {\n "errorCode": 0,\n "message": "Couldn't parse share document: error: Unexpected end of file after null",\n "requestId": "G0IMNTUPI7",\n "status": 400,\n "timestamp": 1435372342014\n}'

Anyway there doesn't appear to be a way to override the Content-type: on POSTs effectively as they will get overwritten with composeRequestCurlOptions() in OAuth1.php or OAuth2.php will set the Content-type to application/x-www-form-urlencoded on a POST request. And the $params sent to this function always assumes you want to POST via http_build_query() which won't work with JSON or XML

Is there a solution for this (I would like to make a pull request as I think I can probably come up with one).

send twitter params

need

return $this->api('account/verify_credentials.json', 'GET', ['include_email' => 'true']);

instead

return $this->api('account/verify_credentials.json', 'GET');

how to?

\yii\authclient\widgets\AuthChoice overrides <a> tag click behavior betwen begin() and end() methods

Migrated from yiisoft/yii2#9241:


@tekord:

I took code from doc page: http://www.yiiframework.com/doc-2.0/yii-authclient-widgets-authchoice.html:

<?php $authAuthChoice = AuthChoice::begin([
    'baseAuthUrl' => ['site/auth']
]); ?>
<ul>
<?php foreach ($authAuthChoice->getClients() as $client): ?>
    <li><?php $authAuthChoice->clientLink($client) ?></li>
<?php endforeach; ?>
</ul>
<?php AuthChoice::end(); ?>

And added <a href="...">Unlink from account</a> inside <li> pair to represent unlinking action, but click on this link has same behavior as click on button generated by clientLink method call.

This happens because JS-script of auth choice widget (vendor/yiisoft/yii2-authclient/assets/authchoice.js) has the following line (line no.34):

$container.find('a').on('click', function(e) {

Click on a tags inside the container starts auth procedure, opens pop-up of current social provider and do their job.

I guess we need ability to customize widget to set selector of that buttons, for example a.auth-action-btn or something like this.

AuthAction requires clientId

The AuthAction requires clientId to be passed by a GET parameter but this is not required by OAuth protocol. I think should be a way to omit this and to specify the client by other ways - via config or a callback function for example. Currently if $_GET[$this->clientIdGetParamName] is empty a NotFoundHttpException is thrown.

Binary Data and CONTENT_TYPE_AUTO exception

I have been using oAuth2 protocol to access Salesforce API's with no problem for json data. However, I am trying to load binary data (blob files) using their api as mentioned here https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_blob_retrieve.htm

As stated:

Document body content is returned in binary form. Note that the response content type will not be JSON or XML since the returned data is binary.

When I try to load this data using this class, I get the following exception thrown as the content type cannot be determined:

if ($contentType == self::CONTENT_TYPE_AUTO) {
      throw new Exception('Unable to determine response content type automatically.');
}

Am I going about this the wrong way? Or should there be a way to specify that content type will be raw / binary / blob but should still be accepted by the OAuth2 class?

Invalid App ID on Facebook Login

Hello like to implement the Facebook login but i bekomme this Error "Invalid App ID 1.044835902206E 15"

'facebook' => [
        'class' => 'yii\authclient\clients\Facebook',
        'version' => '2.5',
        'authUrl' => 'https://www.facebook.com/dialog/oauth?display=popup',
        'clientId' => 1044835902205961,
        'clientSecret' => '26b0a9298608552b9d9df4b87b074176',
    ]

LinkedIn - cannot post to the API

The authclient extension provides an api method used to send API requests. There is a problem when using this method in order to send POST requests to LinkedIn. According to the documentation for sharing content, the proper way to send data is by setting the POST body directly as JSON or XML, not as key-value parameters.

At the moment, this method of sending data is not available within the extension. In the OAuth2 class, the method composeRequestCurlOptions (which internally handles this part of the request flow) treats the parameters as an array and calls http_build_query on them. There are ways around this, such as extending the class and overriding the behavior, but they are rather clunky and they make the developer think more than necessary :)

A possible solution would be to expose a parameter in OAuth2 that controls the way POST data is encoded. Then child classes such as LinkedIn can choose the method they need.

Perhaps this is a bit besides the point of the authclient extension, because it's not strictly authentication-related. Still, this issue does not deal with deep integration between LinkedIn and Yii. Rather, it deals with one of the possible ways to transmit data to an OAuth API. From this point of view, it might make sense to develop a fix.

successCallback not being called

I use the authClient as specified at the quickstart guide (adding the action auth to actions and creating a onAuthSuccess function).

It seems to successfully log me in, since it redirects me to a page I want and gives me a $code variable as a $_GET parameter (that I assume it gets after successful login).

However, that controller does not take into account the successCallback function.

Is there a way I can trace why is the function after a successful callback is not being called?

api wall.post

Привет. Пытаюсь запостить сообщение на стену залогиненому пользователю.

Настройки приложения
api = Включил
тип приложения = standalone

'authClientCollection' => [
'class' => 'yii\authclient\Collection',
'clients' => [
'vkontakte' => [
'class' => 'yii\authclient\clients\VKontakte',
'clientId' => 'прописал id приложения',
'clientSecret' => 'прописал секретный ключ приложения',
'scope' => 'wall,offline'
],
],

public function successCallback($client) {
$attributes = $client->getUserAttributes();
//Пользователь логинится нормально. Получаю по нему все данные.

    print_r($client->api('wall.post','GET',['owner_id'=>$attributes['id'],'message'=>'test'])); exit;
    // [error_code] => 15 [error_msg] => Access denied: no access to call this method
}

Но у меня почему-то ошибка при вызове wall.post. Access denied: no access to call this method

Securing Graph API Requests

Hi.
I do not know whether there was raised the question but I want to ask it.

When using Facebook php yii\authclient\clients\Facebook sometimes an error occurs" api calls from the server require an appsecret_proof argument ". It occurs on facebook if not passed mandatory parameter appsecret_proof.
If you enable additional security check.
Here it is written in more detail - https://developers.facebook.com/docs/graph-api/securing-requests

Fix it pretty easy, you have already done in such class as the LinkedIn / VKontakte. It is enough to override a method Facebook :: apiInternal
adding

protected function apiInternal($accessToken, $url, $method, array $params, array $headers)
{                
    $params['appsecret_proof'] = hash_hmac('sha256', $accessToken->getToken(), $this->clientSecret);        
    return $this->sendRequest($method, $url, $params, $headers);
}

Is it possible to use the safety appsecret_proof without making any changes to class oAuth client?

OpenID discover method always returns 'No servers found!'

I don't know what is the problem, but since my last update of yii2 project with composer the Open ID doesn't discover any server on my Open ID provider, however it was working very well before!
here is the provider address:

http://www.samasoft.ir/SamaSSO/Account/LogOn

as of yii2 docs example:

use yii\authclient\OpenId;

$client = new OpenId();
$client->authUrl = 'http://www.samasoft.ir/SamaSSO/Account/LogOn'; // Setup provider endpoint
$url = $client->buildAuthUrl(); // Get authentication URL
return Yii::$app->getResponse()->redirect($url); // Redirect to authentication URL

it returns :

Exception (Exception) 'yii\base\Exception' with message 'No servers found!' 

in /var/www/SamaNext/vendor/yiisoft/yii2-authclient/OpenId.php:497

I don't know why? Is this my fault? or anything I have to do?

Saving refresh token on authorization

I want to read & modify data on the user's social network that they connected with through yii2-authclient. Some networks' access tokens expire after a certain amount of time and require the supplied refresh token (retrieved when first authorizing an app) in order to get a new access token to read/modify user data. Is it possible to retrieve & save the refresh_token in yii2-authclient returned by an OAuth 2 network so that we can use the access/refresh tokens with the network's API?

Google Plus required?

Hello,
I was wondering why is it necessary to enable Google+ APIs for using authclient with google, since it is possible to retrieve user infomation even with no Google+ API sending a GET request to this endpoint:
https://www.googleapis.com/oauth2/v2/userinfo?key={YOUR_API_KEY}

It should require only these scopes:
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile

This endpoint returns more or less the same info returned by a basic request to Facebook's /me endpoint. Yes, it is actually less than what you get with the current Google+ endpoint, but a lot of it is more than what you need to just implement login

OAuthToken not compatible with Google's access token

By default OAuthToken expects:

Meanwhile Google's OAuthToken consists of the following parameters

  • access_token The token that can be sent to a Google API.
  • refresh_token A token that may be used to obtain a new access token. Refresh tokens are valid until the user revokes access. This field is only present if access_type=offline is included in the authorization code request.
  • expires_in The remaining lifetime of the access token.
  • token_type Identifies the type of token returned. At this time, this field will always have the value Bearer.

How is getToken() for example supposed to return 'access_token' when it looks for 'oauth_token' instead? Am I missing something obvious here?

authclient not accept yii 2.0.6

  1. composer.json add
    "yiisoft/yii2-authclient": "*" or "yiisoft/yii2-authclient": "~2.0.0"
  2. composer responce
    Problem 1
    • yiisoft/yii2-authclient 2.0.5 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    • yiisoft/yii2-authclient 2.0.4 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    • yiisoft/yii2-authclient 2.0.3 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    • yiisoft/yii2-authclient 2.0.2 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    • yiisoft/yii2-authclient 2.0.1 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    • yiisoft/yii2-authclient 2.0.0 requires ext-curl * -> the requested PHP extension curl is missing from your system.
    • Installation request for yiisoft/yii2-authclient * -> satisfiable by yiisoft/yii2-authclient[2.0.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4, 2.0.5].

Now i am copy to /vendor/yiisoft/yii2-authclient last release and ignore Problem 1

Add configurable $baseUrl parameter

Assume there are multiple domains for an OAuth provider (like in wikipedia):

https://en.wikipedia.org/wiki/Special:OAuth
https://ru.wikipedia.org/wiki/Special:OAuth
... etc

So there have to be the choice to pick one:

public $baseUrl;
public $authUrl = '/initiate?format=json&oauth_callback=oob';

Maybe use overridable getters instead of $this->authUrl?

twitter upload/media.json

For use upload image need url upload.twitter.com, now the base url is api.twitter.com, may be added automatically check?

'email' cannot be null error when user disables email on Facebook auth

When a user tries to authenticate with Facebook but disables giving their email, the app returns the following error:
exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null' in /vendor/yiisoft/yii2/db/Command.php:781

After this error, the user can't authenticate anymore and the app always returns this error.

The app shouldn't try to create the account when email is null. It should return an error along with the ability to attempt authenticating again.

Documentation mistak in sql for table auth

sql code mentioned in documentation for auth table

CREATE TABLE auth (
    id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    user_id int(11) NOT NULL,
    source string(255) NOT NULL,
    source_id string(255) NOT NULL
);

while it should replace string filed type with varchar and also fix alter

CREATE TABLE auth (
    id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    user_id int(11) NOT NULL,
    source varchar(255) NOT NULL,
    source_id varchar(255) NOT NULL
)
ALTER TABLE `auth` ADD INDEX ( `user_id` ) ;
ALTER TABLE `auth` ADD FOREIGN KEY ( `user_id` ) REFERENCES `user` (
`id`
) ON DELETE CASCADE ON UPDATE CASCADE ;

https://github.com/yiisoft/yii2-authclient/blob/master/docs/guide/installation.md

Why not remove the dependency of curl extension?

The PHP built-in function file_get_contents(), fully supports all kinds of HTTP requests since 5.0.0.

I strongly hope to cancel the dependence of CURL, I never like to install extra extension, unless there is no choice.

thanks.

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.