Closed kiwiidb closed 2 years ago
An obvious candidate for this authorization flow would be OAuth2. LNDhub.go already uses JWT tokens for Authentication, which integrate well with , and this could be extended for 3rd party Authentication and Authorization. See this repository for a good overview of the protocol and a server implementation in Go. Parts of the examples in this answer come from there.
The problem with OAuth2 is that it is centralized in the sense that the client app needs to connect using a specific host (Github, Google, Facebook,...). In our case, many wallet providers would be possible and they may be self-hosted by the user. So to initiate the OAuth2 flow, it would be better to use a lightning
or lnurl
hyperlink which a user can use with both a mobile wallet or browser-based wallet (Alby). The redirect URL of the OAuth flow would then contain the host where the client app can go to generate an access token and make API calls. This host could be a hosted LNDhub, self-hosted LNDhub (even over Tor if the client app supports it), or a more exotic LNDhub implementation that works through mobile notifications to a mobile non-custodial wallet.
We decided it would be better to follow the normal OAuth flow and use a specific host to integrate as normal. Services could integrate multiple providers (eg. Alby) as they see fit, or they could allow a user to manually input the hostname of their self-hosted provider if they wish to do so.
So the flow could be roughly:
https://getalby.com/authorize?client_name=app_name&redirect_uri=https%3A%2F%2Fwww.example.com&response_type=code&state=somestate&scope=invoices:create%20budget:10000:monthly
.
The possible scopes could be:
invoices:create
: create invoices on behalf of the user (so the user can receive money)invoices:read
: read invoice history, get updates on newly paid invoices through webhookinvoices:keysend:create
: fetch keysend information (pubkey, customKey/customValue)invoices:keysend:read
: read incoming keysend payments and boostagramstransactions:read
: read outgoing transaction history, check payment statustransactions:keysend:read
: read outgoing keysend payments and boostagrambalance:read
: get the user's balancebudget:<SAT_AMT>:<PERIOD>
: be allowed to make payments for up to BUDGET
satoshis per PERIOD
, where PERIOD
should be one of daily
or monthly
. An amount < 0 indicates an unlimited budget.Multiple scopes can be seperated by a space (which should be URL-encoded ofcourse).
The pre-register step to obtain a client id and client secret would be optional, the choice is on the wallet provider if they require it or not.
https
link for web applications or a deeplink to a native or mobile applications.curl --compressed -v https://getalby.com/v1/oauth/tokens \
-u test_client_1:test_secret \
-d "grant_type=authorization_code" \
-d "code=7afb1c55-76e4-4c76-adb7-9d657cb47a27" \
-d "redirect_uri=https://www.example.com"
{
"user_id": "1",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "invoice:create budget:10000:monthly",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
Inside LNDhub, a user would be able to view their linked applications, their permissions, their budgets. They could edit buttons and permissions, see what applications are doing and revoke access to applications.
This OAuth server could be implemented as a seperate service, or as a subsystem of lndhub.go. I am arguing in favour of the latter for the following reasons:
Creating a subdaemon inside lndhub that is used by echo to define a middleware on, has it's own database and controllers seems like the best option.
What do you think about this @bumi ?
@prusnak Do you mind to share your thoughts on my post above? We would like to get some more opinions on this topic :)
I won't provide my own opinion on this topic as I don't consider myself a well experienced web developer. However, my gut feeling is that your direction in this area is good! 👍
Follow-up issue: getAlby/oauth2server#1
Does it make sense to allow account creation via the 3rd party auth flow? If so, how would that work?
Doesn't really make sense I think since the purpose is to allow a 3rd party to access an existing user's account. The creation endpoint should be open to be called without authentication, unless it's been disabled, right?
After a discussion with @bumi I've started to think how we could implement this entire service as a complete stand-alone service / API gateway using https://github.com/go-oauth2/oauth2.
JWT_SECRET
) and inject them when proxying the request to LNDhub (not that these tokens are never exposed to the 3rd party app).This architecture would allow us to ship this feature without any changes whatsoever needed to the existing LNDhub codebase, moving everything to a seperate service (and some front-end client work).
I like the idea that we can implement this standalone and keep lndhub small and flexible.
If we implement a permission system (and for that we can use JWT or macaroons) in LNDHub then by default we would also not require an API gateway. (this could be optional)
The oAuth Server creates access tokens through an API endpoint in LNDHub (authenticated with some admin master user credentials). The 3rd party app then can use those credentials to do calls to LNDHub directly.
This way the initial authentication can be implemented independently of LNDHub and can also be part of another user-facing app (like for example getalby.com in our case)
3rd party app initiates the auth flow and redirects the user to a service-auth page
user authenticates with service
user confirms the permissions
service creates a new access tokens though a new LNDHub permissions API (similar to the /auth call currently)
service redirects the user to the 3rd party app
3rd party app can acquire the access token
3rd party app can do API calls directly to LNDHub authenticated with the access_token
refreshing the token works similar
It should be possible to give an application or service access to your LNDhub account without giving up the full "admin" lndhub connection string. This kind of Authorization could have "create invoice" access, "read transactions" access or "make payment" access with monthly budgets. The Authorization should be time-scoped and a user should be able to have an overview of linked applications and be able to revoke access.