Search code examples
oauth-2.0oauthopenid-connect

How to secure an API with OIDC/OAuth


I'm trying to better understand how to make use of OIDC/OAuth in securing a restful API, but I keep getting lost in terminology. Also when I research this question most of the answers are for Single Page Apps, so for purposes of this question assume the API will not be used for an SPA.

Assumptions:

  • Customers will access a restful API to interact with <Service>.
  • It is expected that customers will create automated scripts, or custom application in their own system to call the API.
  • Once setup it is not expected that there will be a real person who can provide credentials every time the API is called.
  • <Service> uses a 3rd party IDP to store and manage users.
  • 3rd part IDP implements OIDC/Oauth and that is how it should be integrated into <Service>

Questions:

  • What OIDC/OAuth flow should be used in this situation?
  • What credentials should be provided to the customer? client-id/client-secret or something else?
  • What tokens can/should be used to communicate information about the "user"? E.g. Who they are/what they can do.
  • How should those tokens be validated?
  • Can you point me to any good diagrams/resources that explain this specific use case?
  • Am I missing anything important in the workflow?

Solution

  • It sounds like these are the requirements, if I am not misunderstanding you. The solution contains not just your own code and is more of a data modelling question than an OAuth one.

    R1: Your company provides an API to business partners

    R2. Business partners call it from their own applications, which they can develop however they see fit

    R3. User authentication will be managed by each business partner, resulting in a unique ID per user

    R4. You need to map these user IDs to users + resources in your own system

    OAUTH

    Partner applications should use the client credentials flow to get an access token to call the API. Each business partner would use a different credential for their set of users.

    Using your own IDP to store users does not seem to make sense, since you do not seem to have an authentication relationship with the actual end users.

    Access tokens issued to business partners would not be user specific by default. It is possible that a custom claim to identify the user could be included in access tokens - this would have to be developed in a custom manner such as via a custom header, since it is not part of the client credentials flow.

    Access tokens would be verified in a standard OAuth manner to identify the partner - and possibly the end user.

    DATA

    Model users in your own system to have these fields, then store resources (such as orders) mapped against the User ID:

    • User ID (your generated value)
    • Partner ID (company the user is from)
    • External User ID (an ID that is easy for partners to supply)

    Typically each partner would also have an entry in one of your database tables that includes a Client ID, name etc.

    If you can't include a custom User ID claim in access tokens, partners have to tell you what user they are operating on when they call the API, supplying the external user ID:

    • POST /users/2569/orders

    Your API authorization needs to ensure that calls from Partner A cannot access any resources from Partner B. In the above data you have all the fields you need to enable this.

    SUMMARY

    So it feels like you need to define the interface for your own APIs, based on how they will be called from the back end of partner apps. Hopefully the above hints help with this.