ghost blog client id secret showing in head - ghost-blog

I am developing ghost blog for production site using API beta and using view source I can see as below:
ghost.init({
clientId: "ghost-frontend",
clientSecret: "xxxxxxxxxxx"
});
in the html head section, is this right? Isn't secret supposed to be hidden? Although obviously being client meaning it is supposed to be in the client-side.

According to the Ghost Documentation, these credentials are used for Client Authentication. Client Authentication only gives access to the public Ghost API, which is basically anything your readers can currently access on your ghost blog without authentication. So making these credentials public should not be a problem since they can only be used to access public information. Also, the API request must currently come from the same domain as the one specified in your config.js file.
From the Ghost API Documentation:
Please be aware that as of current Ghost versions, Client Authentication is only available as part of the Public API Beta, and only provides access to read public data.
The 'Public' API essentially reflects the behaviour of a blog - it provides
read access to any data that a user/reader of a blog would be able to see.
For the time being Client Authentication is restricted to the domain specified in your config.js file, meaning that requests that come from a theme will work, but requests from another site will not.
And here is why they're doing this:
Ghost’s JSON API has the same abilities as the admin panel (in fact the admin panel uses the API) – so it will eventually be possible to read and write any data you have permissions for using the API. Some data in a blog is inherently public: your published posts, tags, and active users (minus their email and password hash). For this first release, we’re only providing access to read public data.
Additionally, for the first release, we’re only making it possible to read that data from within the theme / frontend of your blog. This is because the ‘client’ authentication that we’re providing only permits requests from internally known domains. All of this will be expanded upon in later releases where there will be a UI to create clients for different kinds of access.
See https://help.ghost.org/article/11-public-api-beta

Related

Next.js restrict the api to my next.js application and my mobile app

Let me clarify my use case:
I have a next.js application which is a plattform for listing real estate objects. I have several api routes which im using inside my next.js app. for example:
/api/createpost ->
Takes informations from my form on my next.js app and creates a database entry to perform a new post
/api/getposts ->
fetching all the real estate posts from my database and displays it
/api/login ->
logs in a user by checking the credentials in the database and sends a jwt
/api/register ->
registers a user by taking the credentials from a form from my next.js app, registering a user and creating an entry in my database
Now in order to secure my apis I want to make sure to check if there is a valid user session if anybody is calling one of the apis (except the register/login api) to get the expected result. Im doing this by calling the /api/login route and getting a valid user session. Until here everything just works fine. Apis like the /api/createpost can only be called if we have a valid user session.
Now I want to create a mobile app and I want to use my api routes from above to provide full functionality in my mobile app too. It should work the same, if i want to call the /api/createpost on my mobileapp for example, i need a valid user session.
But I want to restrict my api by asking for a key in my database which is pointing to my app and saying okay if you call the /api/createpost api, first of all i need to verify that its the mobile app asking. The mobile app will provide the key in the request then.
I didnt try this yet, but it should work i think. Now the big mess: If we call the /api/createpost and the api wants a valid token to check in the database, which will work for the mobile app, because we are giving it a valid token to check in the database, how can we provide a token if we are calling the api from inside our next.js application? Since I have to do the api call clientside, there is no way for me to provide a secret key or something to validate that the call is coming from my next.js application.
If your application is private
(to be used only by you or a few select people)
You can send a private API key over SSL with each request from your application to the server and verify it. Or you can limit your API to only accept requests from certain IPs.
If your application is public
Unfortunately there's no way to determine where the request is coming from, since anything your app can send, an attacker can send it manually.
Think about it, if your app is trying to make a request to your API, any user can intercept this request before its sent out of his/her machine, and send the exact same request from a different app on the same machine.
You might say, well I can encrypt the requests and responses so that they are of no use to the attacker. But such an encryption will require either a key that's already agreed upon, or some way to provide a new key at the beginning of each session.
If the key is already agreed upon, the app must contain it, as you've already guessed in the question, the attacker can retrieve this key no matter how well you try to hide it.
If the encryption key is a new key provided at the beginning of each session, that's almost how SSL works, your browser handles this transaction. Your server sends a public key to your browser to encrypt the requests which the server can then decrypt with a private key. In this case you've circled back to the same problem, how can you verify to whom you give out an encryption key? What would stop an attacker from requesting the encryption key?
There has to be some way you'd be able to design apps that don't require this restriction. I think the question you should be asking isn't how to restrict your api to a certain app, but how to design apps that don't require this restriction.
We might be able to help you out if you could tell us why you need this restriction.
Update
There is actually a way to verify that requests are coming from your app, but not with an api key.
For Webapps
You can use Google's reCAPTCHA to verify a user on your /register and '/login` routes, and provide an access token or start a valid user session on successful captcha response. With reCAPTCHA v3, you could even verify every user action without interrupting the user. This eliminates both the problems I mentioned in my answer above -
You don't have to store an api key into the app/web app.
The request can't be spoofed as it requires human user interaction within your app. The captcha verification success will arrive to your API from Google's reCAPTCHA server, not from your client app. This communication will be authenticated with a pre-mediated private API key shared by Google to you, which works in the same way as to how you authenticate your external domains.
For Android apps
A similar way to achieve the same thing would be via Android SafetyNet Attestation API. This checks the runtime environment and signs the response with a dynamically generated nonce that your app provides the SafetyNet API.
Please read its docs carefully to understand how you could create potential security loopholes and how to avoid them while using this API.
For iOS apps
DeviceCheck works in a similar way, except the device validity is provided to you by Apple server.
Important edit: "secured" is not the right word here! You cannot tell that a request comes from your app just because the domain is yours. The domain name is not a safe information, as it can be altered easily. See #Mythos comments below.
Initial answer:
Web applications access is secured not based on an API key, but based on a whitelist of domains. That's how we achieve security, because only you have access to the domain where you host your own application: so the request has to be coming from an app you own.
If you try some 3rd party services that provides API for web apps, that's often how they'll work: they will let you configure a set of whitelisted domains that can access your data.
If they provide you an API key, this API key is always meant to be used by a server, not a client-only app.
So if I understand you question correctly, you would do like this for each request:
Check the domain. If it's in the whitelist, perfect, you can keep going. This is meant for web apps (look for "CORS").
If not, check for a valid API token in the headers. This is meant for any app that can store this API token securely (another server for instance, or a mobile app in your scenario though I don't know mobile enough to tell how you store such a key)

Static website authentication to firebase backend

Let's say I own a fully static website on https://example.com/. Just HTML, CSS and client side JS files.
Next I wanted to implement a basic commenting system allowing authenticated guests to leave comments. My plan is to use a POST form on the site and implement the commenting backend on Firebase with a Firestore database.
Authentication wise, I suppose it needs to deal with two scenarios:
Client authentication. The site itself needs to be authenticated by the firebase backend so that only POST requests originated from the site will be accepted. What should I do? There must be no shared secret between the site and firebase because the site is static and everything in there can be accessed by visitors. Perhaps there is some kind of host based auth? Appreciated if you can point me in the right direction.
User authentication. Guests need to be authenticated before they can post comments; Use OAuth should be fine provided the backend can deal with Facebook, Github etc.

Calling external APIs having SSO on Azure AD

I have an Intranet authenticating by Azure AD - located at https://intranet.example.com/ (In details, its Sharepoint Online);
In some pages, we need dynamic content generated by an rest api - located at https://api.example.com/ (In details, .NET WebAPI, Owin middleware using OpenId);
api.example auth by AAD too;
Both api.example and intranet.example have Windows Azure AD permission granted through admin consent;
api.example has X-Frame-Options, Access-Control-Allow-Credentials and Access-Control-Allow-Origin enabled to https://intranet.example.com/;
What I need:
Some pages have dynamic content generated by JavaScript logic requesting data from api.example;
Users will authenticate in intranet.example and api.example must have Single Sign On behaviour.
Avoiding any type of prompt or authorize request is a MUST, since all of that must be transparent to the final user;
What I tried:
I tried to simply put an IFrame inside intranet.example pointing to app.example and it works both on Chrome/Firefox. But, IE11 doesnt allow it, since my app redirects to https://login.microsoftonline.com/ that responds with X-FRAME-OPTIONS set to DENY.
Example:
User log in Google Account, access https://mail.google.com/ and have hangouts messages up and running with no prompt or authorize request or something else, totally transparent.
User log in Microsoft Personal Account, access https://onedrive.live.com/ and have Skype messages up and running with no prompt or authorize request or something else, totally transparent.
Note1: It must works outside our domain. So, setting Intranet/Trusted Site Zone is not a option.
Note2: The more decoupled from Sharepoint, the better.
Note3: I tried this aproach PnP Webcast - Calling external APIs securely from SharePoint Framework.
I would recommend re-posting your question in SharePoint Stack
Exchange.
AadHttpClient might be a better option, but it's in preview right now and 'not supported in production tenants'. It also requires the new SharePoint Admin Center which is only available for first release tenants.
Also, I found these to be better AadHttpClient tutorials than the existing MS documentation:
https://www.spdavid.com/consume-a-secured-azurefunction-using/
https://github.com/SharePoint/sp-dev-docs/issues/1378

What is the right way to implement authentication between a WordPress plugin and a Laravel API?

I'm so confused about how to get authentication between an external, consumer website and a Laravel API right. What I'd like is to have a web app for which users are able to present information from the app to other people, using an external website that consumes the app's API. Here's an example of the basic setup in a bit more detail:
A Laravel 5.3 app that has a protected API endpoint api/status. Only authenticated users should be able to hit api/status, and the status returned is a particular status for the authenticated user.
An external website that consumes the Laravel API on behalf of a user, let's call her Alice. The necessary information is stored in the backend of Alice's website so that it can authenticate with the API on behalf of Alice. (The actual implementation I'm working on will be a WordPress site, and the API consumption will be done by a WordPress plugin that I am implementing; so any info stored will likely be stored in the WordPress database.)
The website has a /status page that displays Alice's status to anyone who browses to the page. (Ie, when the /status page is browsed to, an API call to the app is made on behalf of Alice. The returned status is specific to Alice, and is displayed to the person browsing the page.) People browsing to /status on Alice's website do NOT need to do any sort of authenticating to view the status on the page.
That is very simplified compared to my actual goal, but I hope it serves to keep the extraneous details to a minimum so we can focus on my actual question, which is what method of authentication should I use to achieve this?
One thing I DON'T want:
The person browsing Alice's website should NOT be able to use their browser's inspector to watch the API call and from that create further API calls on Alice's behalf on their own.
I have Passport installed on my Laravel App, but if I'm understanding things correctly I don't want to use the basic Access Token issuing workflow, as that would require the people browsing to Alice's website to authenticate using the Alices's credentials. For the same reason, I don't think I want an Implicit Grant Token.
Using a Password Grant Token would require storing Alice's password for the Laravel app on her website. Is it ok to store passwords like this in a WordPress database? It makes me nervous...
The other option available through Passport is to have Alice create a Personal Access Token and store that in her website backend as the token to use to authenticate. But the Laravel documentation seems to imply that Personal Access Tokens are meant for testing and development purposes, which makes me wary of going this route for a production plugin. Plus, doesn't using a PAT make it possible to do the thing I DON'T want above, since the PAT is simply passed in the request header? Or is that problem mitigated by the fact that the API interaction would be done over SSL?
Do I even need to go through Passport to achieve what I want here? Is there a better way?
I've been reading myself in circles trying to understand what the best practice for this kind of setup is. I'm sorry if this question isn't focused enough, but if anyone has any good advice, or can clarify things for me I would much appreciate it!

ASP.NET Cross-Domain Cookies & Facebook Connect

I have a website which i integrate with Facebook (via FBML - JavaScript API).
I have setup the application on Facebook as per normal, specifying the "Connect URL" to be the domain of my website.
However, my application has multiple bindings in IIS for the same website.
Such as:
www.bar.com.au
foo.com.au
The domains are completely different, no relationship in the name whatsoever - so a regex-style rule is not possible (ie base domain). The domains were made different due to a combination of localization and marketing. Keep in mind these domains are baked in to an already live website, in other words i cannot change this architecture.
Is there a way i can specify BOTH of these domain's in the ONE Facebook Application settings for the "Connect URL"? Or will i have to create multiple applications?
Of course i cannot use the "Base Domain" setting as the bindings are not on the same sub-domain.
I actually have around 7 bindings in my website - so i'd rather not have to create 7 seperate Facebook applications - because this means maintaining 7 sets of API key/secret pairs in my application.
alt text http://www.freeimagehosting.net/uploads/268b234e2f.png
What's happening of course is when im on foobar.com.au, the Facebook cookies are not available to the domain.
For the meantime, i will try and create multiple ApiKey's - but i think i might run into issues. I'm going to have to go: "If domain is this, use this ApiKey", then the same logic in every single call to the Graph API. Messy stuff.
So i guess my problem/question isn't really caused by Facebook Connect, its the nature of HTTP Cookies by design.
How can i easily access these cookies cross domain? Will i need to setup a third website and direct all cookie logic to there?
If you want *.foobar.com.au to be allowed, then setup your Base Domain to foobar.com.au.
Could you set one of them up as your "Facebook Authentication" site, and direct all FB Auth-related traffic there, and then use one of a large number of cross-site communication tricks to send the token over to the original site?
In other words, regardless of the site they come in from, you'll use .foobar.com.au (for example) as the redirect URI. Then when they come in to that site with you having noted that they came from .foo.bar.com.au, you'll redirect them back where they came from passing along the access token in some cross-domain fashion (querystring, post vars, etc.)
In my current situation, timeframes have stopped me from doing the proper solution, which is what #Yuliy has highlighted.
For now, i have created multiple Facebook applications. But to keep it DRY, i have abstracted all that away behind exposed properties:
private static string _ApiToken_Site1, _ApiToken_Site2;
public static string ApiToken
{
get
{
if (Site1) return _ApiToken_Site1;
else if (Site2) return _ApiToken_Site2;
}
}
Not exactly clean, but the main thing is i did not have to touch my existing code at all, the smarts to work out which Api Key to use is in that property.
For our next project release, i'll be scrapping this and most likely implementing a WCF/ASMX web service which handles authentication from the one place (ie seperate web service on seperate domain).

Resources