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

WIP: Open Id with Clients Management UI #464

wants to merge 104 commits into
base: master


Copy link

commented Dec 19, 2018

The main goal of this PR is to ultimately allow users on a btcpay system to generate access tokens that could be used to hit the (still unreleased) btcpay api in a popular and standardized way.

There are 2 protocols to look at here: the issuance of an access token and the access token itself.

The issuance of the access token is being done through the Open Id standard which is actually a superset of Oauth 2. It defines multiple ways of how an access token can be issued called Grants
or Flows.
Most of these grants/flows revolve around creating a Client or an Application (whatever you wanna call it) that you specify when starting a grant/flow. A client usually consists of a client Id, client secret, allowed urls able to initiate the flow, and the grants/flows allowed through this client.

Some of the flows are quite simple: they act very much like a traditional api key structure. These are the Password Grant Type/Resource Owner Grant Type and the Client Credentials Grant Type.
• Password Grant Type/Resource Owner Grant Type: you send a request to the open id api specifying your username and password
• Client Credentials Grant Type: you send a request to open id specifying a client id and client secret

The others are not as straightforward however they enable some very flexible and interesting scenarios on how to use BtcPay. Implicit and Code Authorization Flow both allow for ways for an application to receive an access token on behalf of their user without being allowed to handle the user's credentials.

Implicit Flow are by redirecting the user to the btcpay login page( that is initiated through an open id route) and once the user logs in, is redirected back to the original application with the generated access token.

Code Authorization Flow works very similar to Implicit but instead of an access token being directly returned, a special authorization code is given back. This code is then exchanged by the application's backend for an access token.

In general, Code Authorization flows are preferred as they offer a more secure model as you allow a secure backend to only have access to the access token whereas with Implicit flow you transmit it to the client side layer. The rule of thumb here is: If you have an SPA, you use Implicit and if you have some sort of backend doing the api calls, you use Code Authorization.

These only tell our open id system if the client requires a client secret or not( for example a client that allows client credentials must have a client secret and will require that client secret on all initiations of any flow.
• Public Client - no client sercet
• Confidential - has client secret and must always be used in flows
• Hybrid - has client secret but not always used in flows

Some good example usages:
• A new BtcPayServer Management UI that has not backend( only html, css and js) could use the Implicit Flow.
• Enterprise Applications that integrate with BTCPay to manage btcpay and use it as a headless payment processor( where the company uses only the api of btcpay and utilizes it in the background): Client Credentials(preferred) or Password Grant
• A plugin with a backend that uses BtcPayServer.The woocommerce plugin is good real use case,: Authorization Code Flow

  • Integration with BTCPay's claim systems
  • UI to manage API Clients
  • UI to manage refresh tokens issuances
  • Opt-in configuration for stricter levels of OpenId Compliance
  • Persisted RSA signing key
  • Password Flow -Login via user credentials
  • Client Credentials -Login via client id/ client secret
  • Implicit - Trustless login through redirection to btcpayservers' login page
  • Authorization Code - Same as implicit but with a trusted secure storage location
  • Refresh Tokens - Enables us to have short-lived tokens in order to minimize usage of any compromised security key. Refresh tokens can be revoked through the UI.
  • Test Clients Repo
    For information on the what, why and which regarding these flows:

This PR is rather big and has taken quite a bit of effort and time. There are some users already utilizing a small subset of this PR ( specifically password grant flow) in combination with an early preview of a store management API


  • New configuration options:
          public bool EnforceGrantTypes { get;  } 
          public bool EnforceEndpoints { get;  } 
          public bool EnforceScopes { get; } 
          public bool EnforceClients { get;  }

These are different levels of opt-in open id compliance. I would recommend EnforceClients is defaulted to true while the rest are false.

  • Mini cleanup of configurations: Re-used reading of certain config values has been moved to a ConfigurationExtensions.cs with an extension method in order to avoid using hardcoded string keys everywhere

  • The default claim for user id in Auth has been changed to OpenIdConnectConstants.Claims.Subject instead of ClaimTypes.NameIdentifier. Cookie auth still works with this change and it was required to be able to use JWTs.

  • OpenIddict is now a dependency. OpenIddict is the most simplified open id .net implementation I could find. It hooks up with EF Core and ASP.NET Idetntity easily and allows dynamic database-backed client configuration.

  • I have overriden OpenIddict's Client class with our own to link them to a user. Referring to

  • There is a folder under BTCPayServer/Authentication/OpenId which holds a number of *EventHandler.cs files. These are openiddict specifc event handlers and allow us to verify certain type of auth flows against our users.

  • Using the Authorize attribute without an authentication scheme specified will work either with Cookie, or by looking for the authorization Header. If it is a bitpay api route, it will check with bitpay auth too.

  • The server is able to verify access tokens in between running sessions( e.g. restarting btcpay) by persisting an RSA key to the data directory. This is done through

  • Authentication Scheme configuration has been moved to an extension method AddBtcPayServerAuthenticationSchemes. In this method, we handle adding all 3 authentication schemes: JWT Bearer, BitPay Auth and Cookie . This is done by grouping them all in one Authentication policy called Dynamic

  • BTCPayClaimsFilter system has mostly been untouched except for the part where the user id is retrieved. I made use of the UserManager to have a more consistent way of fetching it across the system. I've tested that it works well with all authentications schemes.

  • The Error Page and its view model has been extended to be able to show additional details if provided

  • A Razor Pages directory has been set up and a whole set of UIs has been built using Razor Pages. All viewmodel code is located in the cshtml and is able to be edited and compiled at runtime.

  • There are now UIs to CRUD API Clients, Api Client Authorizations & Api Client Tokens. These are only particularly useful if the EnforceClients configuration option is set to true. I've chosen to make the UI as simplistic as possible and hidden many features to the user.

  • Further to the above point, if EnforceGrantTypes is set to true, a client would also need to select which kind of grant types are allowed with this particulat client. This section of the UI is not visible if not enforced.

  • There were more additional advanced UIs available based on the additional enforcement settings but I chose to leave it out of this PR.

  • Cors has currently been set to allow all origins but I will be changing this shortly

Some screenshots of new UI:






Kukks added some commits Aug 17, 2018

Kukks added some commits Jan 28, 2019

Merge remote-tracking branch 'origin/part3_openiddict' into openiddic…

# Conflicts:
#	BTCPayServer.Tests/AuthenticationTests.cs
Merge branch 'part1_openiddict' into part2_openiddict
# Conflicts:
#	BTCPayServer/Data/ApplicationDbContext.cs
#	BTCPayServer/Hosting/BTCPayServerServices.cs
#	BTCPayServer/Hosting/Startup.cs
#	BTCPayServer/Migrations/ApplicationDbContextModelSnapshot.cs
Merge branch 'part4_openiddict' into openiddict-ui
# Conflicts:
#	BTCPayServer/Hosting/BTCPayServerServices.cs
#	BTCPayServer/wwwroot/main/css/site.css
Merge remote-tracking branch 'btcpayserver/master' into part1_openiddict
# Conflicts:
#	BTCPayServer/Configuration/BTCPayServerOptions.cs

This comment has been minimized.

Copy link

commented Aug 7, 2019

Does this replace the current token based pairing process too? Pairing with Oauth2 would be easier. To connect a client, you’d just have to enter the BTCPay server url, click “connect”, then login with your store admin user and the 2 can be paired.


This comment has been minimized.

Copy link
Member Author

commented Aug 7, 2019

Does this replace the current token based pairing process too? Pairing with Oauth2 would be easier. To connect a client, you’d just have to enter the BTCPay server url, click “connect”, then login with your store admin user and the 2 can be paired.

They will both be available. This PR is only here for reference at this point, check the other open id titled ones :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
2 participants
You can’t perform that action at this time.