So, I have written a quite simple API:
2sxc get api
But when I call this API with the following URL:
https://www.domain.nl/api/2sxc/app/Locaties/api/Searchlocaties/locaties?naam=bo
I get the following message:
{"Message":"Bad Request","ExceptionType":"System.UnauthorizedAccessException","ExceptionMessage":"RequestVerificationToken not present"}
I have set the content and app query permissions to SecurityAccessLevel.Anonymous.
I get the same message even when I am logged in and calling the api using javascript.
fetch('https://www.domain.nl/api/2sxc/app/Locaties/api/Searchlocaties/locaties?naam=bo')
.then(response => response.json())
.then(data => console.log(data));
DNN 9.8 &
2sxc 11.10.1
Has anyone experience this?
All WebApi requests in DNN should include the request verification token in the header, and you usually also need moduleid and tabid.
When using the 2sxc JS API it does this automatically, and the same applies to when using the DNN JS API. But if you use your own call with jQuery or whatever, you must ensure that you add these headers yourself.
You can find various samples here: https://2sxc.org/dnn-tutorials/en/razor/webapi/home
Related
Manifest version 3 for Chrome extensions have been killing me lately. Been able to navigate around it so far, but this one has really stumped me. I'm trying to use Firebase authentication for a Chrome extension, specifically with 3rd party auth providers such as Google and Facebook. I've setup the Firebase configuration for Login with Google and created a login section in the options page of the Chrome extension and setup the Firebase SDK.
Now, there are two login options when using an auth provider, signInWithRedirect and signInWithPopup. I've tried both of these and both have failed for different reasons. signInWithRedirect seems like a complete dead end as it redirects to the auth provider, and when it attempts to redirect back to the chrome-extension://.../options.html page, it just redirects to "about:blank#blocked" instead.
When attempting to use signInWithPopup, I instead get
Refused to load the script 'https://apis.google.com/js/api.js?onload=__iframefcb776751' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
In v2, you could simply add https://apis.google.com to the content_security_policy in the manifest. But in v3, the docs say
"In addition, MV3 disallows certain CSP modifications for extension_pages that were permitted in MV2. The script-src, object-src, and worker-src directives may only have the following values:"
self
none
Any localhost source, (http://localhost, http://127.0.0.1, or any port on those domains)
So is there seriously no way for a Google Chrome extension to authenticate with a Google auth provider through Google's Firebase? The only workaround I can think of is to create some hosted site that does the authentication, have the Chrome extension inject a content script, and have the hosted site pass the auth details back to the Chrome extension through an event or something. Seems like a huge hack though and possibly subject to security flaws. Anyone else have ideas??
Although it was mentioned in the comments that this works with the Google auth provider using chrome.identity sadly there was no code example so I had to figure out myself how to do it.
Here is how I did it following this tutorial:
(It also mentions a solution for non-Google auth providers that I didn't try)
Identity Permission
First you need permission to use the chrome identity API. You get it by adding this to your manifest.json:
{
...
"permissions": [
"identity"
],
...
}
Consistent Application ID
You need your application ID consistent during development to use the OAuth process. To accomplish that, you need to copy the key in an installed version of your manifest.json.
To get a suitable key value, first install your extension from a .crx file (you may need to upload your extension or package it manually). Then, in your user data directory (on macOS it is ~/Library/Application\ Support/Google/Chrome), look in the file Default/Extensions/EXTENSION_ID/EXTENSION_VERSION/manifest.json. You will see the key value filled in there.
{
...
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgFbIrnF3oWbqomZh8CHzkTE9MxD/4tVmCTJ3JYSzYhtVnX7tVAbXZRRPuYLavIFaS15tojlRNRhfOdvyTXew+RaSJjOIzdo30byBU3C4mJAtRtSjb+U9fAsJxStVpXvdQrYNNFCCx/85T6oJX3qDsYexFCs/9doGqzhCc5RvN+W4jbQlfz7n+TiT8TtPBKrQWGLYjbEdNpPnvnorJBMys/yob82cglpqbWI36sTSGwQxjgQbp3b4mnQ2R0gzOcY41cMOw8JqSl6aXdYfHBTLxCy+gz9RCQYNUhDewxE1DeoEgAh21956oKJ8Sn7FacyMyNcnWvNhlMzPtr/0RUK7nQIDAQAB",
...
}
Copy this line to your source manifest.json.
Register your Extension with Google Cloud APIs
You need to register your app in the Google APIs Console to get the client ID:
Search for the API you what to use and make sure it is activated in your project. In my case Cloud Firestore API.
Go to the API Access navigation menu item and click on the Create an OAuth 2.0 client ID... blue button.
Select Chrome Application and enter your application ID (same ID displayed in the extensions management page).
Put this client ID in your manifest.json. You only need the userinfo.email scope.
{
...
"oauth2": {
"client_id": "171239695530-3mbapmkhai2m0qjb2jgjp097c7jmmhc3.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
...
}
Get and Use the Google Auth Token
chrome.identity.getAuthToken({ 'interactive': true }, function(token) {
// console.log("token: " + token);
let credential = firebase.auth.GoogleAuthProvider.credential(null, token);
firebase.auth().signInWithCredential(credential)
.then((result) => {
// console.log("Login successful!");
DoWhatYouWantWithTheUserObject(result.user);
})
.catch((error) => {
console.error(error);
});
});
Have fun with your Firebase Service...
I know firebase sdk have a built in function to verified recaptcha response before doing sign-in with phone number but,
it is possible using manual captcha verifier API return response from https://www.google.com/recaptcha/api/siteverify as 2nd parameter in firebase.auth().signInWithPhoneNumber(phone, apiResponse) ?
I have different case to do it manually.
Thanks
With Recaptcha, you can introduce your own authorization method by using a decodable JWT as a second input. this will require a source of validation to generate the correct token
const captchaVerifier = {
type: 'recaptcha',
verify: () => Promise.resolve(token)
};
Source: https://pastebin.com/kaCarKC5
You could also make your own ReCaptcha that triggers the invisible ReCaptcha or simply use invisible ReCaptcha and implement your own later on per your app's design.
Reference: Invisible ReCaptcha
I'm using the froatsnook:shopify atmosphere package to create an embedded public app on Shopify. I currently have a couple issues:
1) Getting the access token from the "code" query parameter after a user authenticates. As it mentions in the docs here, I'm supposed to use authenticator.getPermanentAccessToken(code) but what I don't understand is how to get call authenticator if the "code" parameter appears on the callback route (at that point, the authenticator I instantiated on the client pre-auth route is out of scope).
2) The "oAuth" function callback is never called for some reason, even when assigning it to Shopify.onAuth on the server.
3) The difference between post_auth_uri and redirect_uri ?
// I call this during 'onBeforeAction' for iron-router
function beforeAuth (query) {
// is this necessary..?
console.assert(Meteor.isClient);
// get shop name like 'myshop' from 'myshop.shopify.com';
const shop = query.shop.substring(0, query.shop.indexOf('.'));
// use api_key stored in settings
var api_key = Meteor.settings.public.shopify.api_key;
// Prepare to authenticate
var authenticator = new Shopify.PublicAppOAuthAuthenticator({
shop: shop,
api_key: api_key,
keyset: 'default',
embedded_app_sdk: true,
redirect_uri: 'https://45a04f23.ngrok.com/testContent',
//post_auth_uri: ???
// This is doesn't seem to be getting
// called after clicking through the OAuth dialog
onAuth: function(access_token) {
ShopifyCredentials.insert({
shop: shop,
api_key: api_key,
access_token: access_token
});
}
});
// Should i use something different with iron-router?
location.href = authenticator.auth_uri;
// how do i get code in this scope???
// authenticator.getPermanentAccessToken(code);
}
There are a few issues with the way you are trying to set up the authenticator, although it's not really your fault because the way Scenario 3 works in the docs is not an 'out of the box' solution and requires a bunch of custom code, including your own handler (I can provide a gist if you REALLY want to build your own handler, but I suggest using the new server-side onAuth callback instead)
1. Specifying a redirect_uri overrides the package's default redirect_uri handler which is Meteor.absoluteUrl("/__shopify-auth").
So instead, completely remove redirect_uri and put your testContent url in post_auth_uri instead.
2. ShopifyCredentials does not exist in this package. If you want to use it that way, make sure you actually have defined a collection called 'ShopifyCredentials' and insert the record from the server, not the client. Note that you will still need to add a keyset on the server for the API methods to work. If you are using user accounts and would like to permanently store credentials, I suggest saving the credentials to the database and adding the keyset via a server-side onAuth callback.
3. authenticator.getPermanentAccessToken(code) isn't useful unless you are using your own handler. Instead, you can just get access_token from the onAuth callback.
Also keep in mind that if you ever need to reauthenticate from inside the embedded app, you need to use window.top.location.href to break out of the iframe.
If you want a complete, working boilerplate example with user accounts see my gist here:
Authentication with Accounts and Persistent Keysets
If you aren't using accounts, you can use this gist instead, but please note that you really need to come up with some way to check that the current client has permission to request the keyset for a given shop before going to production:
Authentication with Persistent Keysets
I have a relatively old Asp.net mvc web project (created around 2012) which used Facebook connect using the AuthConfig.cs file and registered a client as so.
OAuthWebSecurity.RegisterFacebookClient(
appId: WebConfigurationManager.AppSettings["facebookOAuthAppID"],
appSecret: WebConfigurationManager.AppSettings["facebookOAuthAppSecret"]
);
Up until a few days ago when Facebook changed to v2 of their API, all was good but now all is dead when I try to connect. This is where it fails in the account controller.
DotNetOpenAuth.AspNet.AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
Result always returns false, so never continues.
I have found a few examples which inherit IAuthenticationClient and allow you to setup additional scopes etc, and these expose the endpoints that facbook uses. I tried to update these urls to use the new API (v2.3) but still the same error.
Has anyone encountered this and what steps did you do to resolve this?
I am using meteor to create a webpage with a dropdown list of Google Groups to select from and once selected, the Google contacts will be displayed.
I am using HTTP.call POST to Google's API and testing with the accessToken from mongoDB but when I use that token after some time it expires. I looked into implementing an authentication flow but it is getting very complicated since there is no sample code on Google for meteor. I am new to nodeJS, Javascript and Meteor. Am I going about this the wrong way? How would I implement this in meteor?
https://developers.google.com/accounts/docs/OAuth2?csw=1#expiration
To deal with the expiration of the accessToken, you will need to obtain the refreshToken from Google. With this refreshToken, you can obtain a new accessToken whenever necessary via a simple HTTP POST to Google's API. Here is the relevant documentation from Google. To obtain the refreshToken, you will need to request for offline access and may also need to force the approval prompt, as detailed in this SO post.
forceApprovalPrompt: {google: true},
requestOfflineToken: {google: true},
I recommend achieving all of the above using Meteor's HTTP package. All the tools are there. You've probably already figured it out:
var result = HTTP.post(
"https://www.googleapis.com/oauth2/v3/token",
{
params: {
'client_id': config.clientId,
'client_secret': config.secret,
'refresh_token': user.services.google.refreshToken,
'grant_type': 'refresh_token'
}
});
//Do some error checking here
var newAccessToken = result.data.access_token;
refresh_token - The refresh token returned from the authorization
code exchange.
client_id - The client ID obtained from the
Developers Console.
client_secret - The client secret obtained from
the Developers Console.
grant_type - As defined in the OAuth 2.0
specification, this field must contain a value of refresh_token.
result.data will be a JSON object with the following
{
"access_token":"1/fFBGRNJru1FQd44AzqT3Zg",
"expires_in":3920,
"token_type":"Bearer",
}
Have a look at this package its a little wrapper that does auto refresh for you:
here
I actually ended up building my own auth flow for with oauth handler because i needed to move away from a tokens linked to user profiles.