Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication #12

Open
sameh-farouk opened this issue Nov 7, 2022 · 2 comments
Open

Authentication #12

sameh-farouk opened this issue Nov 7, 2022 · 2 comments
Labels
type_feature New feature or request
Milestone

Comments

@sameh-farouk
Copy link
Member

As a user

  • onboarding to the pinning service should be as easy as possible
  • easy way to get the API token

Getting an access token:
Pin services are authenticated via an access token. This is problematic since we want all setup to go though the chain, which means data there is public. As such, the service can't generate an access token and return that. The options are to have the service encrypt something using a shared key, which requires previous key exchange, or to have the client send something to the server which allows it to prove ownership of an access key. To do this, the client can:

generate an access key with some constraints:
hash the access key with a known hashing algorithm (e.g. blake2b-64)
include this hash in the contract on chain
the service can then read the hashed secret. If a client does an authenticated api request, it can check the access token, hash it, and verify that this is a known hash. This way the service has the access keys without direct communication with the client.

This is a subtask of :
#3

@sameh-farouk
Copy link
Member Author

sameh-farouk commented Nov 8, 2022

proposed flow:
User will have two types of keys:

  • User Account secret key -> created by signing up to the service, and involving chain contract creation and user acceptance of the service terms. user will need this secret key to used ( at UI/client side) only when user need to generate and/or revoke (chain verifiable) API keys.
  • pinning service API Key -> used to interact with the TF pinning API endpoints.

Benefits of this Separation:

  • This separation will allow user to revoke and generate new API keys without the need to invalidate the on-chain contract. will explain it further down below.
  • Also, optionally, we can have custom policies attached to the keys and the user can have different keys with different permissions (expire date, specify the endpoints (pin, unpin) that key can used to interact with, number of pins, etc).

Sign up:

  • Overview:
    User can sign up to the service by authorize the service to bill him, this will return to the user a secret key that he can use later for provisioning, revoking API keys without invalidate the chain contract as we will store the public key part of the key pair that will be used to derive the API keys generation.
    Note: Key generation would be done from the client side/ front end. only public key would be sent on wire. secret key will never leave the client side.

  • Steps:
    1- Service will generate a key pair for the user (UI/client side). This avoids bad call by the users (reusing existing keys) also make the process simpler.
    2- Service will create a new chain contract for the user, the public key part will be stored on-chain in the user contract (I will assume that public keys can be looked-up by the twin-id or contract-id) and set different variables on the contract. user will need to accept this contract to start interacting with the service (should involve signing the transaction, e.g, using the polka-dot browser extension).
    3- Service can cache the public key and store it in the user's account (in the service data store) alongside user's twin-id or contract-id. Note: this secret will be used only to interact with the API-key management endpoints (for provisioning and revoking user API key).

  • ENDPOINT:

    • POST /accounts (BODY user-id, payload, timestamp, sig(user-id, payload, timestamp)) Create new contract

API Key Provisioning:

  • Overview:
    User can generate new API key, given his twin-id or contract-id and a secret-key.

  • Steps:
    1- in client side/UI user can provide his secret key to sign something(token) with it. an service endpoint can accept this signed token and the twin id alongside an easy to remember name chosen by the user.
    2- The service will verify that user have a valid contract by:

    • Lookup the chain contacts by twin-id/contract-id and retrieve the public key.
    • ensure the contract exists, and the signed token provided by the user can be verified using the public key retrieved from the user contract.

    3- Service will store the hash of the signed-token, in UI the API-key which will show up to the user only once, as we will store the hash version of it. user will associate it with an easy to remember name, if user lost it he can revoke it by the name, and generate a new one (with his secret key). but he can't retrieve it.

  • ENDPOINT:

    • POST /tokens (BODY user-id, token, timestamp, sig(token+timestamp)) Generate new api-key/token

API key USAGE:

  • Overview:
    The generated API-key/token can be used as an Authorization header for all the API requests (all pinning management endpoints).
  • Steps:
    1- User will connect to the TF pinning API given his API-key using the standard IPFS tools, which uses Bearer Authentication.
    His request will have Authorization header for all API requests in the following format:
    "Authorization": "Bearer YOUR_API_KEY"
    2- The pinning service (auth middle ware) will query the User account (local db) to check that API-key belong to which user (twin-id).
    3- Optionally, The service would retrieve the public key from the chain (user contract) then check if the API-key (which as we know just a signed data) can by verified using the retrieved public key (this check, verifying the API-Key using on-chain data, can be skipped, because as I know the contract data (like public key) should be immutable after both sides accept the contract).
    4- User has been authorized using his valid API-key, and his request/operation will be submitted to the cluster.

API Key Revoking:

  • Overview:
    User can revoke an API key, given his twin-id or contract-id and his secret key, and the custom name of the API-key. As long the user have a valid contract, he can revoke his key, and generate a new one, without affecting his ability to maintain all set of pinning item that has pinned previously as the pins are associated with the user id, not a specific API-key.

  • Steps:
    1- User can authenticate using his secret key to specific rest endpoint by signing a challenge (request data) to revoke one of his owned API-keys, using the API-key name (a display name). or possibly all of his keys.
    2- User can list his keys minus the actual secret-key itself, he can see the name and related info (e.g, policies) only.

  • ENDPOINTS:

    • PUT /tokens/[KEY-NAME] (BODY sig(revoke, user-id, key-name, timestamp)) Revoke key by name.
    • PUT /tokens/ (BODY sig(revoke-all, user-id, timestamp)) Revoke all user API-keys on record.
    • GET /tokens/ (QUERY sig=sig(list-all, user-id, timestamp)) List available keys names.

Canceling Contract:

  • Overview:
    User can cancel his contract (this will involve signing a transaction by his polkadot key), also the contract can be invalidate/canceled for other reasons without user interaction, like out of fund, in both cases this will have these side effects:

    • All API-Keys will be invalidate/deleted, and can't be used any further.
    • All data will be unpinned, this could be done immediately or after specific grace period.
    • The user account will be disabled/deleted and won't be able to be used any further.
  • Steps:
    1- We can relay on that chain can notify us if the user contract was canceled so we can invalidate his API-keys and (possibly, send email, give grace period, finally unpin his data). the service would listen to chain events related to contract cancellation. the service should store last processed block, so in case of any down time, it can catch up the missed events on startup.

  • ENDPOINT:

    • DELETE /accounts/[USER-ID] (BODY sig(delete, user-id, timestamp)) Delete user contract

@sameh-farouk sameh-farouk added the type_feature New feature or request label Nov 14, 2022
@sameh-farouk sameh-farouk added this to the 0.3.0 milestone Nov 14, 2022
@sameh-farouk sameh-farouk moved this to Todo in 3.10.x Nov 14, 2022
@sameh-farouk
Copy link
Member Author

sameh-farouk commented Nov 15, 2022

Update:
Keeping eye on the progress here:
threefoldtech/tfchain#495
Smart contract specs is here:
threefoldtech/tfchain#445 (comment)

@rkhamis rkhamis added this to 3.11.x Mar 28, 2023
@rkhamis rkhamis removed this from 3.10.x Mar 28, 2023
@rkhamis rkhamis modified the milestones: 0.3.0, 0.4.0 Mar 28, 2023
@xmonader xmonader removed this from 3.11.x Jun 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type_feature New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants