Giter Club home page Giter Club logo

mid's Introduction

Mobile ID (MID) REST API

1. Introduction

Mobile-ID (MID) REST interface offers the entry point to main use cases for Mobile-ID:

  • digital signing
  • authentication
  • pulling an End Users's signing certificate

1.1. Terminology

  • Application Provider - provider of the MID service (SK ID Solutions AS)
  • Relying Party (RP) - e-service provider - client for the MID REST API. Authenticates users via MID REST service and/or uses MID REST for users to sign documents inside the e-service.
  • Session - A process initiated by Relying Party, which contains authentication or signing operation.
  • End User - Person that has a mobile phone with Mobile-ID SIM and who initiates authentication or signing in e-service.
  • Mobile Signing - A process where (besides other operations) the hash value of document to be signed is encrypted using secret signing key (stored on SIM-card, protected by 5-digit PIN)
  • Mobile Authentication - A process where generated hash is encrypted using secret authentication key (stored on SIM-card, protected by 4-digit PIN)
  • Verification Code - A 4-digit number displayed both in e-service and in cellphone screen during authentication and signing. See paragraph 2.4 for more info.
  • OCSP - The Online Certificate Status Protocol

2. General description

Mobile-ID API is exposed over REST interface as described below. All messages are encoded using UTF-8. 

2.1. relyingPartyName

Possible string values of RelyingPartyName are agreed between Relying Party and Application Provider during registration. The value from request is checked during authorization and is displayed to the End User on cell phone screen during authentication and signing. This field is case insensitive.

E-Service provider can have more than one relyingPartyName for different e-services.

2.2. relyingPartyUUID

relyingPartyUuid is a shared secret that is handed to Relying Party by Application Provider during registration.

This value contains hexadecimal digits in canonical 8-4-4-4-12 format, for example:    de305d54-75b4-431b-adb2-eb6b9e546014 

E-Service provider can have more than one relyingPartyUUID for different e-services.

2.3. Creating the hash

Relying Party creates the hash using one of the supported hashing algorithms. For signing the document to be signed is the input for the chosen hash algorithm.

For authentication the hash can be random HEX string with correct length. The length has to be one of:

  • 32 bytes = 64 HEX characters (if hashType is SHA-256)
  • 48 bytes = 96 HEX characters (if hashType is SHA-384)
  • 64 bytes = 128 HEX characters (if hashType is SHA-512)

2.3.1. Supported hashing algorithms

MID REST supports signature operations based on SHA-2 family of hash algorithms, namely SHA-256, SHA-384 and SHA-512. Their corresponding identifiers in API are "SHA256", "SHA384" and "SHA512".

2.4. Verification code

Verification code is a 4-digit number used in mobile authentication and mobile signing. Verification code is cryptographically linked with hash value to be signed. Verification code is displayed both in mobile phone and in e-service provider application in order to provide authenticity of the signing request and enable end user to verify what is exactly being signed.

During Mobile-ID authentication and signing it is required that e-service provider calculates verification code from the hash what will be signed and displays it to the user.

2.4.1. Verification code calculation algorithm

6 bits from the beginning of hash and 7 bits from the end of hash are taken. The resulting 13 bits are transformed into decimal number and printed out. The Verification code is a decimal 4-digits number in range 0000...8192, always 4 digits are displayed (e.g. 0041).

Example:

  • Hash value: 2f665f6a6999e0ef0752e00ec9f453adf59d8cb6
  • Binary representation of hash: 0010 1111 0110 0110 1111 .... 1000 1100 1011 0110
  • Verification code – binary value: 0010110110110
  • Verification code – decimal value (displayed for the user): 1462

2.5. HTTP status code usage

All positive responses are given using HTTP status code "200 OK". Cases where end user is not a Mobile ID customer or the certificate of End User is not active are also considered as positive responses and HTTP status code 200 is used.

In some cases, 4xx series error codes are used, those cases are described per request. All 5xx series error codes indicate some kind of fatal server error. 

2.6. Session management 

Main flows of MID REST API - authentication and signing - include involvement from End User who has to enter PIN on the cellphone. As this can take time - these processes are split in two parts:

  • First request initiates the process and immediately returns session id to the Relying Party.
  • Relying Party has to then periodically make status check requests until the process has finished.

Main flows of MID REST API

2.7. Backwards compatibility

MID-REST API-s remain backwards compatible with following exceptions:

  • new request fields may be added over time
  • new fields may be added to JSON responses. Developers need to take this into account when de-serializing JSON fields into objects. For example when using Jackson to de-serialize JSON objects into Java objects the Java classes should be annotated with @JsonIgnoreProperties(ignoreUnknown = true) or the configuration parameter FAIL_ON_UNKNOWN_PROPERTIES should be set to false. Otherwise Jackson starts throwing com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException when a new field is added to a MID-REST API response.

See chapter 3.4. for fetching current API version.

2.8. API endpoint authentication

It is essential that RP performs all the required checks when connecting to the HTTPS API endpoint, to make sure that the connection endpoint is authentic and that the connection is secure. This is required to prevent MITM (Man-in-the-middle) attacks for the authentication and signature protocols.

The RP must do the following checks :

  1. Verify if the HTTPS connection and the TLS handshake is performed with the secure TLS ciphersuite.
  2. The RP must implement HTTPS pinning (https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning) and verify that the X.509 certificate of the HTTPS endpoint belongs to MID API and is trusted. The HTTPS certificate of MID API can be downloaded here: https://www.skidsolutions.eu/en/Repository/certs/other-important-certificates - section "mid.sk.ee"
  3. Verify that the X.509 certificate of the HTTPS endpoint is valid (not expired, signed by trusted CA and not revoked)

These checks are incorporated into:

In case the RP fails to verify the connection security and the attacks is able to launch MITM attack (you can find more info here)

3. REST API flows

BASE: mid-api

3.1. Certificate request

Method

URL

POST BASE/certificate

This method retrieves the signing certificate. Use cases for fetching of the signing certificate:

  • to verify the signature obtained by the signature endpoint (as the signing certificate is not included in the signing response)
  • for embedding the certificate into *AdES-styled digital signatures which require knowledge of the certificate before creating the signature. (See Java code example that first pulls the certificate and then starts the signing process.)
  • to test if end user is a Mobile ID customer.

If end user has two pairs of certificates (RSA and Elliptic Curve Cryptography (ECC)) then system returns preferred certificate (ECC).

3.1.1. Pre-Conditions 

  • User identified in the request (by relyingPartyName, relyingPartyUUID and IP-address)

3.1.2. Post-Conditions

  • Request result has been returned to caller. 

3.1.3. Request parameters

Parameter

Type

Mandatory

Description

relyingPartyName string + Name of the relying party – previously agreed with Application Provider.
relyingPartyUUID string + UUID of the relying party
phoneNumber string + Phone number of the signer with the country code in the format of +xxxxxxxxx
nationalIdentityNumber string + Identification number of the signer (personal national ID number). For example 38412319871

3.1.4. Example request

{
   "relyingPartyUUID": "de305d54-75b4-431b-adb2-eb6b9e546014" ,  
   "relyingPartyName": "BANK123",  
   "phoneNumber": "+3726234566" ,  
   "nationalIdentityNumber": "38412319871"
}

3.1.5. Example response

{  
    "result": "OK",  
    "cert": "MIIHhjCCBW6gAwIBAgIQDNYLtVwrKURYStrYApYViTANBgkqhkiG9w0B...",
    "time": "2019-07-23T11:32:01",
    "traceId": "5ffc28098bb14341"
}

3.1.6. Response structure 

Parameter

Type

Mandatory

Description

result string + End result of the transaction.
cert string for OK result Certificate value, DER + Base64 encoded.
time datetime Since 5.2.1 Used by Application Provider for tracking application logs of any error report.
traceId HEX number Since 5.2.1 Used by Application Provider for tracking application logs of any error report.

3.1.7. Possible result values

For all the result values HTTP status code 200 is used.

Result Reason
OK An active certificate was found
NOT_FOUND No certificate for the user was found

3.1.8. Error conditions

HTTP status code Error message Reason
400 {parameterName} cannot be null. Required parameter in request is missing on has incorrect format/value
401 Failed to authorize user User authorization by relyingPartyName, relyingPartyUUID and IP-address fails
405 Method Not Allowed Only POST and OPTIONS methods are allowed.
500 Internal error MID-REST internal error. Retry the operation.

3.2. Initiating signing and authentication

Different URL-s need to be used to initiate signing or authentication:

Process

Method

URL

Signing POST BASE/signature
Authenticate POST BASE/authentication

3.2.1. Pre-Conditions

  • End User in the request is identified.

3.2.2. Post-Conditions

  • A new session with ID is returned in response. 

3.2.3. Request parameters

Parameter

Type

Mandatory

Description

relyingPartyName string + Name of the Relying Party, previously agreed with Application Provider. Displayed together with displayText and Verification Code on cellphone screen before End User can insert PIN.
relyingPartyUUID string + UUID of the Relying Party - previously agreed with Application Provider.
phoneNumber string + Phone number of the signer with the country code in the format of +xxxxxxxxx
nationalIdentityNumber string + Identification number of the signer (personal national ID number)
hash string + Base64 encoded hash function output to be signed.
hashType string + Hash algorithm used to create the hash.
language string + Language for user dialog in mobile phone. 3-letters capitalized acronyms are used. Possible values: EST, ENG, RUS, LIT. NB! If you use language="LIT" to send to Estonian number (+372...) or you use language="EST" to send to Lithuanian number (+370...) then internally language is replaced with "ENG".
displayText string Text displayed in addition to relyingPartyName and Verification Code before asking authentication PIN. Maximum length is 40 bytes that is either 20 or 40 characters depending on the encoding - see displayTextFormat. If you set displayTextFormat="GSM-7" then all characters not beloning to this alphabet are replaced with spaces.
displayTextFormat string Specifies which characters and how many can be used in "displayText". Possible values are "GSM-7" and "UCS-2”, if nothing is specified then defaults to "GSM-7". GSM-7 allows displayText to contain up to 40 characters from standard GSM 7-bit alpabet including up to 5 characters from extension table ( €[]^|{}\ ). UCS-2 allows up to 20 characters from UCS-2 alpabet (this has all Cyrillic characters, ÕŠŽ šžõ and ĄČĘĖĮŠŲŪŽ ąčęėįšųūž). [More info about encoding](https://en.wikipedia.org/wiki/GSM_03.38).

3.2.4. Example request

{
    "relyingPartyUUID": "00000000-0000-0000-0000-000000000000",
    "relyingPartyName": "DEMO",
    "phoneNumber": "+3726234566",
    "nationalIdentityNumber": "38412319871",
    "hash": "0nbgC2fVdLVQFZJdBbmG7oPoElpCYsQMtrY0c0wKYRg=",
    "hashType": "SHA256",
    "language": "ENG",
    "displayText": "This is display text.",
    "displayTextFormat": "GSM-7"
}

Following dialogues are displayed on end user cellphone screen for authentication and signing. Actual design varies on different phone models.

Prompt for signing Prompt of authentication

Sign prompt on cellphone screen

Auth prompt on cellphone screen

Note that when the process is signing the prompt to End User has "Sign?" in the end and authentication has "Enter?".

3.2.5. Example response

{
  "sessionID": "de305d54-75b4-431b-adb2-eb6b9e546015"  
}

3.2.6. Error conditions

Any response where HTTP status code is not 200 is considered an error condition. HTTP status code 4xx refers to errors made by the Relying Party and HTTP status code 5xx refers to an error on the Application Provider's side.

If authentication or signing is not successful because of End User not entering PIN or due to communication failure this is not considered an error condition but rather a something that can be predicted and expected i.e. it is part of the normal flow.

HTTP status code Error message Reason
400 Required {parameterName} is missing. Mandatory parameter in request is missing on has incorrect format/value
400 The length of the hash must match the type of hash Hash length does not match the type of hash. For example base64 decoded value of SHA256 hash has to be (256bits divided with 8bits) = 32 bytes.
400 Hash must be Base64 encoded Hash is not base64 encoded.
401 Failed to authorize user User authorization by relyingPartyName, relyingPartyUUID and IP-address fails
405 Method Not Allowed Only HTTP methods POST and OPTIONS are allowed
500 Internal error MID-REST internal error. Try start the process again from the beginning.

See next chapter for body of the error.

3.2.7. Error response contents

Example error response contents:

{
    "error": "relyingPartyUUID must not be null",
    "time": "2019-07-23T11:27:49",
    "traceId": "4a295f2786d6dc89"
}

Any error response (when HTTP status code is not 200) contains an error message. This response is meant for the developer to fix the call. There is no need to parse any error responses (where HTTP status code is not 200) and these error messages should not be shown to the End User. Also error responses hold time and traceId parameters which are for Application Provider to find the application logs for any reports about possible errors of MID-REST API.

3.3. Status of signing and authentication

Polling of the authentication and signing status differs from endpoint name to be used.

Process

Method

URL

Signing GET BASE/signature/session/:sessionId?timeoutMs=:timeoutMs
Authentication GET BASE/authentication/session/:sessionId?timeoutMs=:timeoutMs

3.3.1. Pre-Conditions

  • Session is present in the system and the request is either running or has been completed recently. 

3.3.2. Post-Conditions

  • Current session state has been returned to user.

3.3.3. Request parameters

Parameter

Type

Mandatory

Description

sessionId string + Session ID
timeoutMs integer Maximum time in milliseconds the server is allowed to wait before returning a response. See next chapter for more info.

3.3.4. Long polling

In order to avoid making many requests towards Application Provider the E-Service provider is recommended to use long polling by setting parameter timeoutMs.

If the session is in RUNNING state (meaning waiting for user to enter the PIN to the cellphone and the response to arrive) the server waits this amount of time before responding.

If this parameter is not provided, a default is used (can change, value 10000ms). For very large values the service silently reverts to configuration specific maximum value (can change, value around 60000-12000ms). For very low values the service silently reverts to configuration specific minimum value (can change, value around 1000ms)

If the state of session changes during the wait time then the response is sent out immediately. If the wait time is over but the response has not yet arrived from phone then the service responds back that the session is RUNNING and the caller is encouraged to immediately create a new long polling request.

The E-Service provider should not make new requests for given session before the previous request gets a response back. However, if Application Provider detects a new request with the same session ID then the previous request is discarded and response with state=RUNNING is replied back to the previous request.

NB! E-Service provider should set its own internal request timeout to a slightly higher value (add additional ~1500ms). For example if E-Service provider makes a request with ?timeoutMs=60000 then it should set a request timeout of 61500ms (and not use the same value of 60000ms) as it takes additional time to transfer the request and response over the network.

3.3.5. Response structure

Parameter

Type

Present

Description

state string + State of request. One of "RUNNING", "COMPLETE".
result string Only if state is COMPLETE Result of the transaction. See paragraph 3.3.7 for possible values.
signature string Only if state is COMPLETE Structure describing the signature result, if any.
signature.value string Only if state is COMPLETE Signature value, base64 encoded.
signature.algorithm string Only if state is COMPLETE Signature algorithm used, one of SHA256WithECEncryption, SHA256WithRSAEncryption, SHA384WithECEncryption, SHA384WithRSAEncryption, SHA512WithECEncryption or SHA512WithRSAEncryption.

Start of this value reflects the hashType parameter supplied by user (SHA256, SHA384 or SHA512). If EC (Elliptic Curve) or RSA is used - this depends on which certificates the End User has available on the SIM-Card. If SIM-card has both types of certificates available then Application Provider selects the type of certificate by its internal preferences (these preferences can change over time).

cert string Only if process was authentication and signature is present. Authentication certificate used. DER + Base64 encoded. From the certificate it is possible to obtain end user name, national identity number and country. See [mid-rest-java-client](https://github.com/SK-EID/mid-rest-java-client) or [mid-rest-php-client](https://github.com/SK-EID/mid-rest-php-client) for examples how to parse the certificate.

Signing process doesn't return a certificate. To obtain the certificate used to create the signature make a separate request (see 3.1.). NB! The authentication certificate can't be used to verify the signature returned by the signing process.

time datetime Since 5.2.1 Used by Application Provider for tracking application logs of any error report
traceId HEX number Since 5.2.1 Used by Application Provider for tracking application logs of any error report

3.3.6. Verifying the authentication response

For authentication additional steps must be followed to verify that the authentication result is trustworthy and identity of the End User is confirmed:

  • "result" has the value "OK"
  • "signature.value" is a valid signature over the same "hash", which was submitted by the Relying Party.
  • "signature.value" is a valid signature. This can be verified by using the public key taken from the certificate returned on the "cert" field.
  • The person's certificate given in the "cert" is valid. This means it is:
    • not expired
    • signed by trusted certificate authority
  • The identity of the authenticated person is in the "subject" field of the X.509 certificate included in "cert" field.

After successful authentication, the Relying Party must also invalidate user's browser or API session identifier and generate a new one.

3.3.7. Example responses

Response when server is still waiting for user's response to arrive back from cellphone:

{
    "state":"RUNNING",
    "time": "2019-07-23T11:36:16",
    "traceId": "460ef8a6be5730da"  
}

Signing response after successful completion:

{
    "state": "COMPLETE",
    "result": "OK",
    "signature": {
        "value": "B+C9XVjIAZnCHH9vfBSv...",
        "algorithm": "SHA256WithECEncryption"
    },
    "time": "2019-07-23T10:52:20",
    "traceId": "d8de38e7bb5d8f8a"
}

Authentication response after successful completion (note that unlike signature response it also includes authentication certificate):

{  
    "state": "COMPLETE",
    "result": "OK",
    "signature": {
        "value": "B+C9XVjIAZnCHH9vfBSv...",
        "algorithm": "SHA256WithECEncryption"  
    },
    "cert": "MIIFxjCCA66gAwIBAgIQZ6v2ut9...",
    "time": "2019-07-23T10:52:20",
    "traceId": "d8de38e7bb5d8f8a"
}

If user cancelled the operation:

{  
    "state": "COMPLETE",
    "result": "USER_CANCELLED",
    "time": "2019-07-23T11:36:38",
    "traceId": "2f3bebf7036c51f1"
}

When response from end user's cell phone has not arrived within a timeout period set by Application Provider. The Application Provider has given up waiting for it to arrive and responds with:

{
    "state": "COMPLETE",
    "result": "TIMEOUT",
    "time": "2019-07-23T11:36:11",
    "traceId": "bc861f0cf0568570"
}

3.3.8. Session end result codes

The following is a complete list of possible result codes returned by the service. For all of them a HTTP 200 status code and a JSON string is returned with "state": "COMPLETE" and "result" with one of the following values:

Result Reason
OK Session was completed successfully
TIMEOUT There was a timeout, i.e. end user did not confirm or refuse the operation within maximum time frame allowed (can change, around two minutes).
NOT_MID_CLIENT Given user has no active certificates and is not MID client.
USER_CANCELLED User cancelled the operation
SIGNATURE_HASH_MISMATCH Mobile-ID configuration on user's SIM card differs from what is configured on service provider's side. User needs to contact his/her mobile operator.
PHONE_ABSENT Sim not available
DELIVERY_ERROR SMS sending error
SIM_ERROR Invalid response from card

3.3.9. HTTP error codes

Error code Error message Reason
400 Required sessionId is missing Required paramter sessionId is missing.
401 Failed to authorize user User authorization by sessionId and IP-address fails
404 SessionID not found Sessions expire within 5 minutes.
405 Method Not Allowed Only GET and OPTIONS are allowed methods.
500 Internal error MID-REST internal error. Try start the process again from the beginning.

3.4. API version

Method URL
GET BASE/version

3.4.1. Example response

    Version: 5.1.1. Built: 19.06.2019 21:06  

3.4.2. Response structure

    Version: MAJOR.MINOR.PATCH. Built: dd.MM.yyyy hh:mm

Version numbering:

  • MAJOR version is incremented when a new API is released or if there have been major internal changes. See chapter 2.7. for notes about API backwards compatibility.
  • MINOR version is incremented when there are smaller internal changes, new request parameters or new response fields are added.
  • PATCH version is incremented with backwards-compatible bug fixes. No fields are added with bug fixes.

Built timestamp refers when the release was built from source code.

3.4.3. Public demo environment version number

Open link: https://tsp.demo.sk.ee/mid-api/version

4. Helper libraries and demo applications

There are client libraries provided for easier integration for Java and PHP and also demo applications that demonstrate usage of the client libraries.

4.1. Java

Java Clint allows using all of the MID-REST functionality.

4.2. PHP

Provided PHP functionality only supports authentication and fetching the signing certificate.

5. OCSP

The Online Certificate Status Protocol is an Internet protocol used for obtaining the revocation status of an X.509 digital certificate. See Validity Confirmation Services offered by SK for more information.

5.1. OCSP Necessity

When digitally signing AsicE and Bdoc containers by standard then for the signature to be valid it is required to perform OCSP for signer's certificate at the time of signing and include OCSP response as part of the signature. MID-REST doesn't perform any OCSP requests.

5.2. Implementing OCSP

Digidoc4j performs the OCSP during signing process and includes OCSP response it in the signature. For testing purposes, it is possible to use Test OCSP by building the signature Container with Test Configuration. To use test ocsp you need to upload your signing certificate here.

Configuration configuration = new Configuration(Configuration.Mode.TEST);

Container container = ContainerBuilder.aContainer()
    .withConfiguration(configuration)
    .withDataFile(uploadedFile)
    .build();

mid's People

Contributors

alvar-sk avatar jalukse avatar aasaru avatar rasmuskukk avatar andrevka avatar ttoomema avatar

Stargazers

Svajūnas avatar Mantas Mikulėnas avatar Trevor Himma avatar  avatar M. Faraz avatar Bojan Ilievski avatar Thales Ribeiro avatar Heiko Kase avatar Tormi Tabor avatar TiX avatar Dmitry Buzdin avatar Leho Kraav avatar Kaido J. avatar Mika Tuupola avatar Kaspar Rosin avatar Andri Möll avatar  avatar Juozas V. avatar Igor Volkov avatar Natallia Sitnikava avatar Vitaly Mosin avatar Soheil Rashidi avatar Martin avatar Mart Sõmermaa avatar

Watchers

Leho Kraav avatar James Cloos avatar Meelis Lilbok avatar Tõnis Reimo avatar  avatar  avatar  avatar  avatar Semjon Kravtšenko avatar  avatar Svajūnas avatar

mid's Issues

MID Authentication - Personal Data

Is (or will be) there a way for the Relying Party to retrieve the End User personal details using the new REST API such as Name, Surname, Date of birth, gender... and so on?

Signature value for EC signatures is not DER encoded

While it is possible to use an RSA signature directly as a signature value in a CMS SignedData structure the value of an EC signature is a raw 64 byte-string which needs to be processed and embedded into a valid structure.

From RFC5753, item 2.1.1:

  • signature MUST contain the DER encoding (as an octet string) of a
    value of the ASN.1 type ECDSA-Sig-Value (see Section 7.2).
  ECDSA-Sig-Value ::= SEQUENCE {
    r INTEGER,
    s INTEGER }

This should be documented or fixed. It is also required to rebuild such structure to be able validate this kind of signature with common tools.

Imprecise documentation about certificates

While implementing MID signing in Python, I encountered an issue that a signature I was getting from the signature endpoint could not be verified using the certificate returned by the authentication endpoint.

Please make the docs more clear about the fact that to verify the signature you need the certificate endpoint.

3.1. Certificate request
This method is necessary for *AdES-styled digital signatures which require knowledge of the certificate before creating the signature. For other types of digital signatures knowledge of the certificate is not needed.

This is misleading because you do need this certificate to verify the signature. I suggest replacing this phrase by:

This method is necessary for successful verification of the signature obtained by the signature endpoint, and for embedding the certificate into *AdES-styled digital signatures which require knowledge of the certificate before creating the signature.

3.3.5. Response structure
| cert | Authentication certificate used. DER + Base64 encoded. Signing process doesn't return this value (need to pull separately). ...

I suggest formulating this clause as follows:

Certificate used to create the authentication signature. DER + Base64 encoded. Signing process doesn't return a certificate, to obtain the certificate used to create the signature make a separate request as per 3.1. The authentication certificate can not be used to verify the signature returned by the signing process.

Receive response instantly from authentication session status request

From API documentation on 'timeoutMs':

For very low values the service silently reverts to configuration specific minimum value (can change, value around 1000ms)

So each authentication session status check request waits minimum 1 second before returning a response.

Currently implementing Mobile-ID authentication in a service where it is not practical to keep threads open by long-polling styled solution.
We are querying authentication session status multiple times (with delayed ~5 second timeout in between) in a synchronous manner and expect response to be returned immediately.
That minimum 1 second adds up in keeping the threads busy and might become a burden as load increases.

Could that limit be removed or lowered?
Is the only reason of that minimum to prevent incorrectly implementing clients from spamming the service?

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.