Giter Club home page Giter Club logo

draft-dpop's People

Contributors

adeinega avatar b---c avatar danielfett avatar dcreado avatar dteleguin avatar hyperparabolic avatar ioggstream avatar jogu avatar jricher avatar panva avatar selfissued avatar

Stargazers

 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

draft-dpop's Issues

SPA recommendations

As sent earlier via the mailing list.

I don't know if this belongs to the DPoP document itself or each respective BCP (especially Browser-Based Apps), but one of the documents should give recommendation to implementers on how to

  1. generate the unique private keys per installation / browser session
  2. platform specific storage for them (e.g. in between browser navigation / app launches)

I come asking for this guidance especially for the Browser-Based App use case. I think the clear recommendation is to use the Web Cryptography API (with extractable: false) for (1) and IndexedDB API for (2), but the more important question is how to deal with lack of those APIs in browsers that are known to not support them or be buggy (see data in https://caniuse.com), so

  • is it ok to use other means of generating the key when webcrypto is not available?
  • is it ok to generate keys through webcrypto (or other means) that are extractable and store them via other means than IndexedDB when indexed DB is not available, such as cookie or localstorage.

jti requirements for replay prevention

https://tools.ietf.org/html/draft-fett-oauth-dpop-01#section-11.2 has

11.2.  Token Replay at the Same Resource Server Endpoint

   If an adversary is able to get hold of a DPoP-Proof JWT, the
   adversary could replay that token later at the same endpoint (the
   HTTP endpoint and method are enforced via the respective claims in
   the JWTs).  To prevent this, clients MUST limit the lifetime of the
   JWTs, preferably to a brief period.  Furthermore, the "jti" claim in
   each JWT MUST contain a unique (incrementing or randomly chosen)
   value, as proposed in [RFC7253].  Resource servers SHOULD store
   values at least for the lifetime of the respective JWT and decline
   HTTP requests by clients if a "jti" value has been seen before.

However, the "(incrementing or ...)" part might be problematic and lead to collisions and false positives on replay checks if jti alone is what is stored and checked server side when multiple clients (even instances of clients) are incrementing from the same or similar values for jit. The server would need to track jti values qualified by the public key or something. And I'd think at that point it'd be easier to just say to track the whole JWT (or a hash thereof) for replay prevention.

Or drop the "incrementing" part for jti and also have a minimum suggested or required entropy for unlikelihood of collisions globally. Probably 128 bits - i.e. 16 secure pseudorandom bytes that are base64url encoded gives something like "jti": "_ltc11acc9_ESC4bwc3u-8"

I guess the https://tools.ietf.org/html/rfc7519#section-4.1.7 definition of jti really kind of says that already. But I think people will see "incrementing" and potentially get it wrong. So some guidance might be useful. At least removing ""incrementing".


   The "jti" (JWT ID) claim provides a unique identifier for the JWT.
   The identifier value MUST be assigned in a manner that ensures that
   there is a negligible probability that the same value will be
   accidentally assigned to a different data object; if the application
   uses multiple issuers, collisions MUST be prevented among values
   produced by different issuers as well.  The "jti" claim can be used
   to prevent the JWT from being replayed.  The "jti" value is a case-
   sensitive string.  Use of this claim is OPTIONAL.

Recommend mTLS if possible

Should we be more explicit about recommending to implement mTLS instead of DPoP if that suits the use case?

Do we need DPoP key rotation?

Key rotation would enable a client, when using a refresh token, to provide a new DPoP key.

I can come up with two situations where this might be useful:

  1. A client just wants to follow good crypto practices and rotate the DPoP key in regular intervals. I do not, however, see situations where the client's DPoP key would be compromised and the client would not be royally screwed anyway. Not sure if this is actually needed therefore.
  2. The DPoP key used by a client is contained in an external JWKS (e.g., referred to by client metadata jwks_uri). The keys in this JWKS are rotated in regular intervals and the client does not want to make an exception for the DPoP key. In that case, the clients needs to rotate the DPoP key as well.

Both are not really strong cases. Any other thoughts on this?

contradictory recommendations on reuse vs. replay prevention of proof JWT

Section 5 has this recommendation that clients reuse the same proof JWT.

   It is RECOMMENDED that clients reuse the same JWT if possible to
   improve the performance of the client, the data transfer (caching),
   and the authorization server.

However there are several places (listed below) where the recommendation is for the server to track jti values of proof JWTs to prevent replay. The recommendations seem problematic, if both client and server followed them.

https://tools.ietf.org/html/draft-fett-oauth-dpop-01#section-4

 o  "jti": Unique identifier for this JWT chosen freshly when creating
      the JWT (REQUIRED).  SHOULD be used by the AS for replay detection
      and prevention.  See Security Considerations [1].

https://tools.ietf.org/html/draft-fett-oauth-dpop-01#section-5

   8.  if replay protection is desired, that a JWT with the same "jti"
       value has not been received previously.

https://tools.ietf.org/html/draft-fett-oauth-dpop-01#section-6

   9.  if replay protection is desired, that a JWT with the same "jti"
       value has not been received previously.

https://tools.ietf.org/html/draft-fett-oauth-dpop-01#section-11.2

   Furthermore, the "jti" claim in
   each JWT MUST contain a unique (incrementing or randomly chosen)
   value, as proposed in [RFC7253].  Resource servers SHOULD store
   values at least for the lifetime of the respective JWT and decline
   HTTP requests by clients if a "jti" value has been seen before.

Possible token exfiltration consideration

I believe there are three attack vectors due to logic injection in public clients: 1

  1. the inspection and possible exfiltration of unprotected state
  2. the augmentation/modification of behavior
  3. the inspection and modification of traffic

Under mTLS and token binding, you can still view and modify state, behavior, and traffic - but we assume you can't exfiltrate the tokens because you can't capture and recreate the TLS setup.

For these however, if the client private key or TLS implementation can be modified as part of the application, the crypto information can be exfiltrated along with the tokens.

With DPoP in a browser, I can put the key into WebCrypto which will cause the platform to manage it as non-exportable, but if an attacker managed to get a service worker installed they can potentially view and modify the communication with the AS. They could alter the proof token to bind to their own exportable key, and even modify the headers on other requests in an attempt to disguise that the key and tokens had been exfiltrated.

[1]: Native apps can have issues due to bundled malicious code and dynamic library/code loading, such as remote update frameworks and advertising libraries. But Javascript rightfully has a reputation since preventing arbitrary code execution is manual or opt-in.

passing of dpop in resource request.

Good afternoon, using this first comment to join the group and threads.

I believe the draft should be updated to capture a sample request to a resource server. Such that we can see the presence of the extra header.

Authorization: Bearer
xxxxx:

Note: T-Mobile has a practice with "x-authorization" containing the pop token generated by the client.

Eliminate proof vs binding JWTs by externalizing JWK

One of the things I really like about the mutual TLS spec is that the client authentication and certificate-bound access tokens are usable independently of one another.

To that end, I would like to propose binding to a JWK be done by supplying that JWK in a separate header alongside a DPoP proof token, rather than defining a separate binding token and header for the case where it needs to be supplied.

What this would allow:

  1. Simplification, there would be a single DPoP JWT type/format
  2. The ability to potentially use a pre-established key by reference in the case of a registered /confidential client
  3. The ability for native clients to leverage DPoP proofs against a public key sent via mTLS, if desired

I'm also assuming here that certain parties will wish to leverage DPoP as well as more sophisticated request parameter/header/body signing to perform end-to-end integrity protection/non-repudiation of requests to resource servers.

The only consequence thats obvious to me with the current design is that there would no longer be a different DPoP JWT sent for creation of an access token vs refresh of an access token - but since the tokens are meant to be cryptographically bound, I don't see this as an issue.

use "iat" instead of "exp"

The combination of jti and iat gives a better replay window protection than putting exp in the hands of the client. The exp field should be a SHOULD NOT.

Naming inconsistency - "pop" versus "dpop"

The draft uses both the token_type identifier "pop" and the identifiers DPoP-Binding, dpop-binding+jwt, etc. We should either use the string "pop" or "dpop" consistently in all our identifiers.

I'd advocate for simply "pop" - with the presumption that our draft eventually carries the day.

extract definition of Proof/Binding JWT

the structure of the JSON payload is the same in all use cases, the only difference lays in the public key carried in the header in case of a binding message. Its definition should be given once (whereas it is now given in Section 3 and 4.

Discuss headers vs. request parameters

As far as I understand sending credentials im headers is best practice these days. So I'm not sure we need to "cope" with preflight requests by passing the dpop binding and proof as request parameters.

Let's discuss the implications of headers with respect to CORS/preflight requests.

uniqueness requirements on jti

The comment thread on issue #32 veered into discussion of the use of exp vs iat and was closed to "continue the discussion in #38". However, I believe the original problem in issue #32 is still a potential complication so this is a new issue to track it.

https://tools.ietf.org/html/draft-fett-oauth-dpop-02#section-9.1 has:

Furthermore, the "jti" claim in each [DPoP proof] JWT MUST contain
a unique (incrementing or randomly chosen) value, as proposed in
[RFC7253]. Resource servers SHOULD store values at least for the
time window in which the respective JWT is accepted and decline HTTP
requests by clients if a "jti" value has been seen before.

The "(incrementing or ...)" part might be problematic and lead to collisions and false positives on replay checks is jti alone is what is stored and checked server side when multiple clients (even instances of clients) are incrementing from the same or similar values for jit. The server would need to track jti values qualified by the public key or a hash thereof or something like that. And I'd think at that point it'd be easier to just say to track the whole JWT (or a hash thereof) for replay prevention.

I found the reference to RFC7253 not to be helpful. We are talking about nonce like things in both but the context is pretty different as is the scope of uniqueness and the consequences of repetition. I highly suspect that a developer looking at OAuth and DPoP will not be happy with a reference to the whole document on "The OCB Authenticated-Encryption Algorithm" as advice about setting jti claim values.

I would suggest dropping the "incrementing" part for jti guidance and rather have a minimum suggested or required entropy to ensure that the likelihood of collisions is approaching zero. Probably 128 bits is good enough - i.e. 16 secure pseudorandom bytes that are base64url encoded gives something like "jti": "_ltc11acc9_ESC4bwc3u-8".

A client could start a series of requests with a pseudorandom jti and increment each subsequent one from there. The doc could mention that. But, as I read it anyway, "incrementing" in the doc now suggests that a client could start from 1 and count up. Which would likely lead to problems.

referal-binding

should we support referal binding flows?

with the dpop process we want individual client instances to generate and use their own key pair. but the client instance may still be using a client server to supply client secrets in the Code flow. If the client secret has been added then the dpop may be invalid. (destination url...
).

ie...

client . ----> client_server --->token endpoint

should we enable the client_server to make the token request, but then make a referered binding so the access_token issued is issued to the client's key instead of the dpop the client server is capable of making.

ie...
client server supplies

{
"iss":"clientid",
"iat":1552875882,
https_uri:"resource path"
referred_binding
}

http_uri syntax underspecified

The draft currently defines http_uri as "The HTTP URI used for the request (REQUIRED)." We should probably say whether there are restrictions on whether a fragment may be included, whether the URI must use the "https" scheme, whether query parameters may be included, etc.

Also, I think that "HTTP URI" should be changed to simply "URI".

Symmetric Keys as an Option for RS Proofs

I've been talking to several large scale API operators about DPoP. A consistent concern is the CPU cost of doing an asymmetric key validation on every HTTP Request at the RS.

Micro-benchmarks on this are easy to make, and at lower in the protocol stack, eg TLS, there is only one asymmetric operation before a symmetric key is exchanged, so maybe DPoP as it stands would be hard to deploy.

I think the primary concern is at the RS level of validation. Depending on the RS, the "work" of a request can be highly variable, so adding a single asymmetric key operation could be a significant portion of CPU usage at scale.

In my discussions, at the AS layer, there is a general belief that the request rate and overhead of validating a DPoP signature can be OK. (I work at Okta -- the AS CPU usage is important too, but we already do a bunch of "other" expensive work on token requests, such that adding one more EdDSA validate is a rounding error in the short term).

Supporting HS256 or similar signing of the proof would be one way to reduce the CPU usage concerns.

The challenge seems to be getting the symmetric key to the RS in a distributed manner.

This use case could be scoped as a separate specification if that makes the most sense, building upon DPoP.

Throwing out a potential scheme here:

  • 5. Token Request (Binding Tokens to a Public Key): The request from the client is unchanged. If the AS decides this access token should use a symmetric key it:
  1. Returns the token_type as DPoP+symmetric
  2. Adds a new field to the token response: token_key. This should be a symmetric key in JWK format, encrypted to the client's DPoP-bound asymmetric key using JWE. This means the client still must be able to decrypt this JWE before proceeding using its private key.
  • 6. Resource Access (Proof of Possession for Access Tokens): The DPoP Proof from the client would use the token_key issued by the AS.

  • 7. Public Key Confirmation: Instead of the jkt claim, add a new cnf claim type: JSON Encrypted Key or jek. The jek claim would be an JWE encrypted value, containing the symmetric key used for signing the DPoP proof header in the RS request. The JWE relationship between the AS and RS would be outside the scope of the specification -- many AS's have registries of RS and their capabilities, and might agree upon a symmetric key distribution system ahead of time, in order to decrypt the jek confirmation.

I think this scheme would change RS validation of an DPoP-bound proof from one asymmetric key verify, into two symmetric key operations: one signature verify on the DPoP token, and potentially one symmetric decrypt on the jek claim.

Inclusion of dpop+jwk cnf value should be a MUST rather than SHOULD

The draft currently says "Access tokens that are represented as JSON Web Tokens (JWT)[RFC7519] SHOULD contain information about the DPoP public key (in JWK format) in a member dpop+jwk of the cnf claim."

It seems to me that this SHOULD should be a MUST. When would an implementation not want/need this?

exp is a number

but an example in -01 has "exp": "..." which kinda implies it is a string value. It should probably be "exp": ... or why not a real value "exp": 1556791216?

flesh out the examples

Flesh out the "..." in examples like "DPoP: eyJhbGciOiJSU0ExXzUi..." and "Authorization: DPoP eyJhbGciOiJIUzI1..." to have real complete JWTs that are conformant to this document.

I think (some anyway) implementers and spec aficionados find that kind of thing to be super useful.

I plan to do this work. This issue is mostly just a placeholder/reminder.

token_type pop conflicts with definition in draft-ietf-oauth-signed-http-request

draft-ietf-oauth-signed-http-request also defines token_type pop. Assuming that draft-ietf-oauth-signed-http-request stays dead, this isn't a problem. But I wanted to call out the conflict so that we're aware of it.

I view this as a tracking issue - not a bug - and I don't propose any action to address it at this time.

typ value dpop-proof+jwt or dpop+jwt?

The draft uses the typ values dpop-proof+jwt and dpop+jwt. Which is intended?

Also note that the IANA registration for the typ value is for pop, which should be changed to the intended value above.

Underspecified statement about "token_type"

The last sentence of Section 5 says "The client MAY use the value of the "token_type" parameter to determine whether the server supports the mechanisms specified in this document." This seems underspecified to me. How does the client use this and under what circumstances would it do this?

IANA Considerations need some work

Resource Access (Proof of Possession for Access Tokens) https://tools.ietf.org/html/draft-fett-oauth-dpop-02#section-6 is using "Authorization: DPoP <...>" while OAuth Access Token Type Registration https://tools.ietf.org/html/draft-fett-oauth-dpop-02#section-10.1 has "HTTP Authentication Scheme(s): Bearer" which doesn't quite add up. Should check https://tools.ietf.org/html/rfc6749#section-11.1 for how registration is supposed to be done and https://tools.ietf.org/html/rfc6750#section-6.1 for the only(?) example in practice.

The authorization scheme may need to be registered somewhere. I don't know how this works. Need to look into it.

I don't believe that "dpop+jwt" type value registration is quite right in https://tools.ietf.org/html/draft-fett-oauth-dpop-02#section-10.2. It's supposed to be a media type per https://tools.ietf.org/html/rfc7515#section-4.1.9 and https://tools.ietf.org/html/rfc7519#section-5.1 . Note that there's already the registered "+jwt" structured syntax suffix from https://tools.ietf.org/html/rfc8417#section-7.2 but I think maybe a media type registration is still expected. Honestly, I wonder if explicitly typing the DPoP proof JWT actually adds anything of value? I know the JWT BCP recommends explicit typing but the context of use is really different as are the potential issues.

New JWT claims need registration (http_method and http_uri) or public names.

The "DPoP" HTTP header needs registration.

The "jkt#S256" confirmation member for of the "cnf" claim needs to be registered.

There may be other stuff so an additional review with IANA stuff in mind is probably warranted, if this thing gets adopted on the RFC track.

Backwards-Compatibility of DPoP

Should DPoP be usable by a client even if the AS/RS do not support it?

DPoP is currently designed such that it can be used by a client even if the AS/RS do not support DPoP. To this end, the client adds headers that do not interfere with a normal operation of the AS/RS. The client can observe (via the token_type=Bearer-DPoP value) whether the particular AS supports DPoP. There is no way of knowing whether the RS supports DPoP. The current approach requires that, in order to be backward-compatible, the access token type sent to the RS is Bearer (in the Authorization header). This is not a clean design for two reasons: 1. The token type communicated by the AS to the client is Bearer-DPoP, not Bearer. 2. The token is not actually a Bearer token, since the client needs to prove possession of a key.

I see three potential solutions:

  1. Do away with the backwards compatibility. DPoP introduces a new token type and we use that token type in the Authorization header. We could optionally add the DPoP-Proof into that header as well. If a client receives a token_type=Bearer response from the token endpoint, it could switch DPoP off or abort the transaction.
  2. Get rid of the new token type and still call it a Bearer token. Potentially create another way for the Client to learn whether the AS/RS supports DPoP, either via a new parameter or via metadata.
  3. Keep the current, inconsistent, state of affairs.

I strongly favor Option 1.

Add syntax for using DPoP with the implicit flow

In conversations with @ve7jtb and @danielfett at IIW, I communicated that Microsoft also needs syntax for using DPoP with the implicit flow. John said that all should be required is a syntax for passing the PoP key in the authorization request. He suggested doing so via a signed OAuth request.

Finish fleshing out the examples as legal JSON

For instance, replace "exp": "..." with an exp clause with an actual value. (For instance, choose a NumericDate value that represents Daniel's birthday at some point in the future, if you like!

Add Error codes

(see also errors in RFC6750, extend/copy if necessary)

  • dpop-binding JWT is not validating
  • dpop-proof JWT is not validating

Normalization of URIs might break DPoP

As Nat pointed out, trailing slashes that are removed by a web server automatically might break the signature in DPoP. Other problematic cases include double slashes and internally rewritten requests.

An approach to tackle this problem might be to include the URI that was signed by the client in the DPoP proof. This way, the AS/RS can apply whatever custom normalization/rewriting logic they like before checking the signature.

Delete "(remainder of JWK omitted for brevity)"

The last line of Figure 3 is "(remainder of JWK omitted for brevity)". First, this isn't a JWK, so this doesn't make sense. Please either delete this or replace it with an example element that makes sense in context.

IANA Considerations needed

The draft needs to register several values in IANA registries:

  • The "pop" token_type,
  • The "dpop+jwk" parameter,
  • The "DPoP-Binding" value (or whatever it ends up being called),
  • etc.

I'd be glad to write the IANA Consideration section after we submit -00.

size matters in matters of size

The DPoP proof JWT is relatively small (kinda) already but space can be at a premium in HTTP headers (especially, for example, when there might also be a JWT access token in the Authorization header). There are a few pieces of static content that could be tightened or removed to make the DPoP proof a bit more space efficient and maybe the bound access token a bit smaller too.

The core RFC 7519 claim names are all three characters so as to be "short because a core goal of JWTs is for the representation to be compact." DPoP could follow suit and use htu and htm rather than http_uri and http_method respectively to save 13 characters in the payload, which is ~18 characters in the encoded token. It could even go to two characters with hu and hm.

Given the claims content, how keys are used and communicated, and the general context of use, I cannot think of any reasonable way that a DPoP proof could be legitimately confused for a different meaningful and valid JWT in a different context. Or vice versa. As such, the "typ":"dpop+jwt", could be dropped to save 17 characters in the header, which is ~23 characters in the encoded token.

Using jkt#S256 for the confirmation member name was roughly following the convention from JOSE for the x5t and x5t#S256 headers where SHA1 was the hash alg for x5t and the #S256 part was added to indicate SHA256. The OAuth MTLS document went with "x5t#S256" for the confirmation method member name to try and be consistent with the JOSE headers and JWK parameters. But there's nothing preexisting for a JWK Thumbprint hashed with SHA1 and there's not going to be. So I think it'd be just fine for DPoP to use jkt for the SHA256 JWK Thumbprint confirmation method member name. That'd trim 5 characters from introspection responses and the body of JWT access tokens, which is ~7 characters of an encoded JWT access token.

preventing downgrade in a mixed support scenario

A DPoP-bound access token must be sent in the Authorization header with the prefix DPoP. For such an access token, a resource server MUST check that a DPoP header was received in the HTTP request, check the header's contents according to the rules in (#checking), and check that the public key of the DPoP proof matches the public key to which the access token is bound per (#Confirmation).

In my opinion an RS must also check the presence and value of the DPoP Proof JWT when an Access Token (introspected, JWT-verified, or otherwise...) contains cnf with jkt so that simple use of Bearer scheme with a constrained token value doesn't end up returning a protected resource.

http_method syntax underspecified

The draft currently specifies http_method: as "The HTTP method used for the request (REQUIRED)." We should probably specify that the method be spelled using only lowercase ASCII characters.

(I suspect we don't want "GET", "get", "GeT", "geT", etc.)

AS metadata, client metadata

Iโ€™m thinking the OP should expose metadata about the supported signing algorithms.

A dynamically registered client might also announce the algorithm it intends to use.

This is parallel to token_endpoint_signing_alg client metadata and token_endpoint_auth_signing_alg_values_supported AS metadata.

example EC JWK not fully to RFC 7518

Per https://tools.ietf.org/html/rfc7518#section-6.2 the 'octet string MUST be the full size of a coordinate for the curve specified in the "crv" parameter' for x and y but the examples in -00/01 have a "y" that is too short to be full sized for P-256. It's unusually short compared to anything that I've seen before - I'm curious, where'd this key come from? https://tools.ietf.org/html/rfc7517#section-3 has an example showing the x and y the same length.

Also the use of "kid" seems a bit out of place in the given context. Is there some reason for it?

access token and dpop containing a redundant CNF

Apology if this was covered in a previous discussion.

I notice that the current md draft has a CNF in the at+jwt (good) and in the dpop+jwt (redundant?) If the Dpop is provided in the Token request then i can understand why the cnf might be added to the request. but for the more numerous resource requests I work that a lazy developer may take the CNF from the dpop to validate the same dpop defeating the entire binding.

The contrstruct b64'...' is not legal JSON

The document contains example values like b64'usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8' - which are not legal JSON. We need to replace these with base64url-encoded string values.

Use of unintroduced terminology "DPoP-Proof JWT or a DPoP-Binding JWT"

The Token Replay Security Considerations section uses the terminology "DPoP-Proof JWT or a DPoP-Binding JWT". This came as a surprise at this point in the draft, as these terms weren't adequately previously introduced.

I figured out what you meant by searching back in the draft, but other readers will be likewise surprised.

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.