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

Oauth support? #40

Open
husafan opened this issue May 7, 2022 · 6 comments
Open

Oauth support? #40

husafan opened this issue May 7, 2022 · 6 comments

Comments

@husafan
Copy link

husafan commented May 7, 2022

https://alpaca.markets/learn/connecting-to-oauth/

How useful is this? If I am understanding correctly, to be able to run commands as a given user, the APCA_API_KEY_ID and APCA_API_SECRET_KEY need to be available in the environment or the tool should enable OAUTH permissions, allowing the user to log into their account and providing the CLI with an authorization code?

The biggest open questions I have are:

  1. How would you provide a redirect URL to a command line utility?
  2. Does this enable anything that can't be done with APCA_API_KEY_ID/APCA_API_SECRET_KEY?

Thanks for helping me understand this.

@d-e-s-o
Copy link
Owner

d-e-s-o commented May 7, 2022

These are all good questions. To be frank, my understanding of OAuth is shaky at best, so I may not be of that much help here. I don't actually have use for OAuth support. It mostly made the list for the sake of completeness; perhaps I should have left it out. Also, it's a standard more often than not lamented as overly complicated.

I've written one OAuth client and for that service you could actually register and specify a redirect URL on localhost. But to this day I am not entirely sure it was fully blown OAuth ;-)

  1. How would you provide a redirect URL to a command line utility?

I'd think that should happen via an environment variable.

  1. Does this enable anything that can't be done with APCA_API_KEY_ID/APCA_API_SECRET_KEY?

I think there is some appeal for long running applications/services, where you could basically revoke access on a per application basis after an access token expires (whereas with key-id + secret you'd only be able to revoke access for everything and you'd need to restart clients [or provide new credentials somehow]). And typically you can grant access to certain features of the API only. But these are all non-use-cases for me at the moment.

At least if localhost redirection is supported (which I don't know is the case with Alpaca), it also may make it easier to build authenticated-by-default services in your local network. E.g., if you assume your local network to be trusted, you could have a service there that does all the OAuth stuff and then hands out tokens to your individual applications. Then, all each application would need to know is the address of this local service. It could retrieve a token from said service and then issue requests directly to the Alpaca API, merely providing the token. That would kind of centralize authentication, which may make sense in certain scenarios (and not so much in others) [but I am not sure this is anywhere in the intended-use ballpark for OAuth]. But you could certainly build something somewhat similar without OAuth, by just redirecting all requests to a service that adds authentication information (wouldn't be as nice, though).

Anyway, in general, I think OAuth is useful for larger web services. As per my understanding, GitHub, for example, offers OAuth access and so services such as GitLab (or tons more) can be granted limited access to parts of the API in the context of a certain user. E.g., GitLab CI may be allowed to install a web hook for a repository to get informed about pull requests and then fetch the updated repository history, but it may not have permission to modify repository history etc.


All that being said, as probably came across by now, this is a low-priority, low-impact feature, with some potential for rejection should it add too much complexity. It's also entirely conceivable that the functionality should simply not reside in apca itself, but be built on top and be located in a different repository (I think we'd need a better picture of the parts involved first to make that call). As such, I am not sure I'd recommend you taking it on.

Now, not to hijack the issue, but if you are interested in other work in this environment, the biggest impact from my perspective would be hooking up portfolio history support in apca and then plumbing it through into apcacli. I'd think it's a useful feature to have and missing support is somewhat shameful -- at least if I am correct in my understanding of what it can be used for :P

Aside from that, what I think would also be really nice is to add extension support to apcacli. What I mean by that is basically having a way to write scripts/programs that can be invoked as an apcacli sub-command, similar to how you can write git or cargo sub-commands. We have written something like that for nitrocli. From my perspective, most of that could be copied to apcacli. A discussion thread with most of the design discussions is d-e-s-o/nitrocli#50 (though not everything is applicable) and the main part of the implementation d-e-s-o/nitrocli#112 (likely more relevant). I don't recall all the details off the top of my head, so I don't know exactly how much is transferable and whether there needs to be some design work.
Anyway, this would be really nice to have and would allow us to move functionality that is currently stand-alone into the repository. E.g., I have a program that is useful for mostly manual trading, which basically ensures that stop orders are present for all positions that are above a certain percentage gain (which I see I haven't even published yet).

Lastly, another task would be to convert apcacli from using structopt to using clap v3, which is the new kid on the block for argument parsing (well, sort of). If you are interested in writing command line applications in Rust in the future, any knowledge gained as part of that task would be transferable.

@husafan
Copy link
Author

husafan commented May 8, 2022

I think OAuth is mainly useful for building web services that trade on behalf of a given customer. For example, assuming I wanted to use the apca library to write an Alpaca-based trading application, I'd follow the instructions for creating a new app, then when users log into my app, I would redirect them to the OAuth endpoint, which would return an authorization code to my server once the customer authenticates with Alpaca. I would then exchange this code for an access token using a POST as described in step 6 of the docs: POST https://api.alpaca.markets/oauth/token or POST https://paper-api.alpaca.markets/oauth/token.

Given this flow, I propose a lower cost solution which I think is appropriate to the scope of this library: support the authorization code -> access token exchange via the above POST requests, as well as updating the client to be able to use access tokens (instead of API keys) to make calls to Alpaca. This would allow a server to utilize the apca library to create a new client using, for example, AccessTokenInfo instead of ApiInfo.

What do you think?

As for the other tasks you mention, I would be happy to help with them. This has been a great experience in my journey to learn Rust and you have provided some great guidance. Do you want to go ahead and create feature requests in the apca and apcacli repos, and I can pick them up as I start to work on them?

@d-e-s-o
Copy link
Owner

d-e-s-o commented May 8, 2022

Given this flow, I propose a lower cost solution which I think is appropriate to the scope of this library: support the authorization code -> access token exchange via the above POST requests, as well as updating the client to be able to use access tokens (instead of API keys) to make calls to Alpaca. This would allow a server to utilize the apca library to create a new client using, for example, AccessTokenInfo instead of ApiInfo.

Yeah, that's also what I'd think would fit in here. The rest (some local service or so) would be in a different repository. That being said, without this rest I am not sure how much value the addition of AccessTokenInfo provides. We'd at least need a way to test it (i.e., making requests with it). And right now it looks as if that at the very least requires some bespoke setup involving a globally reachable server (unless we can register a localhost redirect URL, in which case we'd still need a local service). I'd probably just put this issue on ice for now and until we have an actual use case; then we can revisit.

As for the other tasks you mention, I would be happy to help with them. This has been a great experience in my journey to learn Rust and you have provided some great guidance. Do you want to go ahead and create feature requests in the apca and apcacli repos, and I can pick them up as I start to work on them?

Happy to hear that. Sounds good, I will open some issues.

@husafan
Copy link
Author

husafan commented May 8, 2022

Good point. I'll do a little bit of research and see if Alpaca does anything to make this flow easier for the paper API.

If not, I will drop it for now. I guess we can leave this open so others can find it?

@d-e-s-o
Copy link
Owner

d-e-s-o commented May 8, 2022

I guess we can leave this open so others can find it?

Absolutely.

@sbeam
Copy link

sbeam commented Oct 19, 2022

FWIW, thanks for leaving this open, I'm glad to see it is under consideration. I will eventually have a need for exactly the use case you described, though I'm a long way off and can use API keys for now. If I can be of any help lmk, I agree testing OAuth is a bit of a challenge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants