Use Admin API from Firebase Cloud Function

That’s something you do on the cloud server provider.

1 Like

Yes, sorry, my bad I thought I had done that but I hadn’t. Glad you pointed it out. It now works! The only thing I now wonder is if this is totally secure, since I’m sending requests to http and not https. Someone could, potentially, steal the origin header key right? Can I somehow use https?

Definitely don’t use the admin API over a public network with HTTP. You can reverse proxy to it for HTTPS but you’ll probably need a separate Caddy process to do that.

I’m working on remote management features currently. Might take a little while before I have something to show, but it’s in the works.

1 Like

Hm. Yeah, it didn’t seem right.

Is reverse proxy my only option? Seems a bit complex, any pointers on how I would go about doing something in that way?

I went with Caddy because of the API features and easy SSL-issuing and maintaining. My main goal is for clients domains to be added to my server and get a SSL-certificate automatically, without me doing anything manual (except of course the setup beforehand).

It’s simple, really, just like any other HTTP reverse proxy:

example.com

reverse_proxy localhost:2019

Stand something like that up in front of your main instance and then you can access it over HTTPS. This is just until the admin endpoint has native HTTPS support. (It’s a bootstrapping problem, you see, how do we load the config for HTTPS when the admin panel that loads config needs HTTPS?)

1 Like

I see, yeah the bootstrapping issue is at least complex! :wink: Can I do the reverse proxy with a single caddy instance on a single Digital Ocean droplet or would I have to start a new one up?

You can use one droplet, but will have to use at least two processes. If you do it within the same process, Caddy’s admin endpoint will wait for the reverse proxy to close gracefully before the admin endpoint will return, but the reverse proxy will wait for the admin endpoint to return before it will close gracefully (the result is a forceful disconnect).

1 Like

EDIT:
I got it all to work now using a simple reverse_proxy.

Massive thank you both @matt and @francislavoie for guiding me through this and also for your dedication to the Caddy project. Wish Caddy the best of luck! :smile:

1 Like

@francislavoie @matt

Hi again!
As we left off some days ago I got this to work with Origin header authentication in Postman. But when I now try to use axios and send this custom header it won’t work and I get "Refused to set unsafe header “Origin” " error in Chrome console.

I have added this to my reverse_proxy to the admin API server:
header_down Access-Control-Allow-Origins *
And I get this header returned when I call the endpoint, so it seems to work.

I know this might be related to axios, but when I’ve searched all over the internet it doesn’t seem to be any library that can send a custom Origin header in an API-request. This error seems to me like it’s the Chrome (or is it axios?) user-agent refusing to send a custom origin header.

So is there some way I can get this to work using this Origin “authentication method hack” or do I need another solution? :slight_smile:

Browsers won’t allow you to set that header.

Instead, you should use the domain itself for the origin check. Something like <secret>.example.com, and make sure that subdomain will resolve to the right place.

1 Like

@francislavoie Hm, what domain should I use how? My reverseproxy domain or the domain I´m sending the request from? I’m planning to send it from a Firebase Cloud Function. And what should it resolve to? The admin API server?

Thinking about it some more, I don’t think you’ll be able to do this directly from the browser, for those reasons above. The browser sets the origin to whatever is in the address bar, basically, so you can’t really have a “secret” in there in any useful way. You really would need to have some other backend service that exposes an API that could then make the request to Caddy’s API.

From a security perspective, it seems like a terrible idea to be making the requests from the browser anyways, because then whoever has access to the site making the request would have the secret, so you’d be opening the hole for abuse.

@francislavoie Hm… Yeah. Back to square one again :wink:

My idea was not to send the requests directly from the browser but from a Firebase Cloud Function, so at least another layer there. But yeah, still.

I’m sitting here thinking about a smart way to do this. Or at least A way.

What you’re saying is that maybe I should have an API which I can call, that maybe has some other way of authentication (bearer, user/pass or something?). That, in turn, sends the origin header to the admin API?

Any pointer on how I can do this with two instances of Caddy? Currently I have one which is the server I’m trying to configure (with the admin API) and one is a reverse_proxy to that that looks something like this in the Caddyfile:

api.mydomain.co

reverse_proxy <ip-address-to-admin-api>:2019 {
    header_down Access-Control-Allow-Headers *
    header_down Access-Control-Allow-Origin *
}

@francislavoie I have browsed around a bit and wondered if I maybe could use basicauth somehow to protect the reverse_proxy? But I haven’t figured out how though, if even possible.

Of course it’s possible. :slight_smile: Did you read the docs and examples?

1 Like

@matt Hi, yes I did but wasn’t quite sure still. Could this work?

api.mydomain.co

basicauth * {
	username <hashed_password>
	
	reverse_proxy <ip-address-to-admin-api>:2019 {
        header_down Access-Control-Allow-Headers *
        header_down Access-Control-Allow-Origin *
    }
}

Hmm, I think you would find this page helpful: Caddyfile Concepts — Caddy Documentation – it will describe the Caddyfile structure to you. (You can’t arbitrarily put directives inside other directives. The Caddyfile is mostly flat.)

2 Likes

@matt Thanks, yeah I sometimes get lost between JSON structure and Caddyfile, although it should be easy :sweat_smile:

Maybe this then? Will this protect an API request with basic auth? :slight_smile:

api.mydomain.co

basicauth * {
	username <hashed_password>	
}

reverse_proxy <ip-address-to-admin-api>:2019 {
        header_down Access-Control-Allow-Headers *
        header_down Access-Control-Allow-Origin *
        header_up Origin <secret-origin-key>
}

Well, did you try it? :wink:

1 Like

@matt I get what you try to get accross :wink: I’m just very new to server management and proxies and so on, so just wanted to make sure I wasn’t completely barking up the wrong tree here.

I did try it now however, but it still seems to not work when calling it from a browser, only from Postman… I get this in the browser (screenshot below), even though I have a Access-Control-Allow-Origin * in my Caddyfile, and that response header is shown in Postman. Am I missing something here? :slight_smile: I’m thinking it might have something to do with basicauth not allowing the OPTIONS preflight request made from the browser, or similar…

BROWSER

POSTMAN

CADDYFILE

api.velosity.co

basicauth {
    username <hashed-pass>
}

reverse_proxy <server-ip-address>:2019 {
    header_down Access-Control-Allow-Origin *
    header_up Origin <origin-token>
}