Making Azure Mobile App accept custom authentication with Node backend - node.js

I'm trying to implement a custom authentication in an Azure Mobile App (not the old Mobile Service) with a Node.js backend, with actions I can't quite translate into Node. An earlier question states that custom authentication "just works" with a .NET backend. I am having trouble getting
I have copied Joy of code's example JWT generation (gist here). I invoke it like this (inlining the aud and userId):
zumoJWT(expiry,"MyAud","MyAud:1455527189540927",req.azureMobile.configuration.auth.secret);
My registration API returns the following JSON
{"user":{"userid":"MyAud:1455527189540927"},"token":"a lot of base64"}
Which I put into the Android MobileServiceClient with this code
JsonObject userob=ob.get("user").getAsJsonObject();
MobileServiceUser user=new MobileServiceUser(userob.get("userid").getAsString());
user.setAuthenticationToken(ob.get("token").getAsString());
mClient.setCurrentUser(user);
Which gives me the error message
com.microsoft.windowsazure.mobileservices.MobileServiceException: {"name":"JsonWebTokenError","message":"invalid signature"
The next time I invoke an API. How do I make my app accept the login token?
Edit: The server-side logs say
2016-02-15T11:42:35 PID[180] Warning JWT validation failed: IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 1,
Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
)
',
token: '{"alg":"HS256","typ":"JWT","kid":0}.{"exp":null,"iss":"urn:microsoft:windows-azure:zumo","ver":2,"aud":"MyAud","uid":"MyAud:1455534835642715"}
RawData: a lot of base64'..

I figured it out. I needed to have
mobile.configuration.auth.validateTokens=false;
in app.js (or rather, not have the same variable set to true).

Related

Need help and guidance for accessing operationId in nodejs application

We are using nodejs as my backend application and react native in front end. And azure application insights for logging. In UI side, we are redirecting to Stripe checkout page(external page) for payment and then coming back to our application's confirmation page. Here we are loosing the flow on end-to-end transaction. My requirement is to link pre-stripe and post-stripe operation into one single flow. For this my approach of solving this problem is accessing OPERATIONID and pass it to stripe and receive it back from Stripe and use it in confirmation page so that we will one single flow. I Need help in guiding me to the right documentation/ solution proposals.
I read some articles(eg: How to get Application Insights operation id in javascript?) and figured out that operationId is a uniqueID which gets created out of my application and cant access it in the application. I tried to use below code and got response of that operationID as "ai.operation.id" but seems like this is not the right pattern(value) of operationId.
import { defaultClient } from 'applicationinsights';
const telemetryClient = defaultClient;
// tslint:disable-next-line:no-console
console.log(telemetryClient.context.keys[`operationId`]);
The main function of operationId is to help tracking distributed systems so you can correlate requests. So as given in this documentation in nodejs client, you should set the setDistributedTracingMode to appInsights.DistributedTracingModes.AI_AND_W3C as shown below.
const appInsights = require("applicationinsights");
appInsights
.setup("<your ikey>")
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)
.start()
You should be able to get the operation id using the following code snippet.
const AppInsights = require("applicationinsights");
var context = AppInsights.getCorrelationContext();
var oid = context.operation.id;
If it does not solve your problem then, I would suggest you to set telemetry.context.operation.id to be a unique id by yourself and confirm if this is tracked by the Application Insights properly.
Also note that the latest version of the JavaScript SDK (SDK v2) for Application Insights have some changes as given in this document.
Moved context.operation to context.telemetryTrace. Some fields were also changed (operation.id --> telemetryTrace.traceID).
To keep the trace ID unique, where you previously used Util.newId(), now use Util.generateW3CId(). Both ultimately end up being the operation ID.
For more information read this log custom telemetry document.

How to configure keycloak-(nodejs-)connect to use PKCE?

I have an express app that I want to secure with keycloak-connect. I have not found any documentation or examples of how to set up an Authorization Code Flow with PKCE in this middleware.
I think I have configured Keycloak (IDP) correctly, because authentication from the app fails due to the middleware not transmitting neither code_challenge nor code_challenge_method parameters, which the auth server rejects:
auth_callback
1
error
invalid_request
error_description
Missing parameter: code_challenge_method
state
b720bdf4-daf8-4aa7-8525-be02404396a6
Middleware configuration:
{
realm: 'SomeRealm',
'auth-server-url': 'https://auth-server.url/auth/',
'ssl-required': 'all',
resource: 'Some-client-ID',
'public-client': true,
'confidential-port': 0,
}
Is keycloak-connect even capable of utilising this flow?
keycloak-connect does not support PKCE as of now.
See the discussion I found at https://keycloak.discourse.group/t/keycloak-connect-node-js-pkce/8285 There someone suggests to switch to another library, which supports PKCE (i.e. node-openid-client)
Regarding the server configuration, I guess you followed https://www.keycloak.org/docs/latest/server_admin/#advanced-settings and section about PKCE, so that should be working as expected.

passport-apple inexplainable invalid_client on nodejs backend -- using clean example repository with fresh set of credentials

I've cloned https://github.com/ananay/passport-apple-example and replaced the config with this:
clientID: "com.myname.web",
teamID: "myteamid",
callbackURL: "https://myurldev.com/auth/apple/redirect",
keyID: "mykeyid",
privateKeyLocation: path.join(__dirname, "../apple-key.p8")
I've also added SSL certificate on my machine and starting the server with https, all works fine & is recognized by my browser. I'm also starting the app on port 443 and proxying using my hosts file myurl.dev.com -> 127.0.0.1.
I have the same auth setup for facebook, google & microsoft and everything works fine.
I have:
Created a new APP identifier and enabled Sign in with Apple for it, named it: com.myname.dev
Created a new SERVICE identifier and enabled Sign in with apple, called it: com.myname.web
Added "https://myurldev.com/auth/apple/redirect" to the "Reply URLS" on the service identifier com.myname.web
Set my app identifier com.myname.dev as the main app identifier my service to be grouped with.
Created a private key and enabled sign in with apple, interface confirmed the presence of grouped ID com.myname.web bundled with com.myname.dev for which the key was created.
I have confirmed using console.log that the private key is indeed at the path being passed as parameter.
converted the .p8 file to base64 & then back to UTF-8 in an attempt to use the string for privateKeyString
successfully implemented Apple Oauth several times in the past using passport-apple
This time around, for some reason, auth simply doesn't work.
If I set the clientID as the APP identifier, not the service, I'm getting
invalid_request
Invalid web redirect url.
instead of invalid_client
Any advice on debugging this is highly appreciated. Thank you.
EDIT #1:
I have dug a bit deeper into the passport-apple package to figure out if anything goes against apple's docs around token generation, but the flow never reaches that part, indicating things go wrong on the actual configuration in Apple's console & what I'm trying to use for my project.
EDIT #2
2 of the app Ids I have created always throw "wrong redirect uri" because they're not service IDs so I can't configure redirect_uri, this will change if to "required" if I pass undefined as a redirect_uri.
One of the app ids throws only invalid client_id instead, regardless if I pass undefined or good value for redirect_uri.
EDIT #3
Went full vanilla through the OAuth code flow process and just created a url & redirected the user it, failing with this method is consistent with what is happening when using the passport-apple module.
const url = new URL("https://appleid.apple.com/auth/authorize");
url.searchParams.append("state", "fdbd287b1f");
url.searchParams.append("response_type", "code");
url.searchParams.append("scope", "name email");
url.searchParams.append("response_mode", "form_post");
url.searchParams.append(
"redirect_uri",
"https://raiseitupdev.com/auth/apple/redirect",
);
url.searchParams.append("client_id", "com.myname.web");
return res.redirect(url.toString());
[Creator of the library here.]
Did it stop working in development too? I feel this is a configuration error because the actual thing is working live on my website:
https://passport-apple.ananay.dev
Please follow up on this Github issue. Thanks!
https://github.com/ananay/passport-apple/issues/23

Can we use firebase crashlytics for our web application?

I have a web application and I want to track its crashing reports.
Can I use Firebase crashlytics or Fabric for this purpose. In their site its mentioned its only for Android or ios.
Regards,
Makrand
There is feature request: https://github.com/firebase/firebase-js-sdk/issues/710
Looks like it's not supported at all, fabric didn't supported crashlytics on web either so it looks like there are maybe some alternatives like https://www.bugsnag.com but I would like to have it too in one place. Don't see difference between web, android or iOS clients at all, don't know why this is not supported.
But for some possible solution for Vue framework is to catch errors and send it to google analytics where you can connect also your firebase mobile apps. I think to try it this way for now. I didnt tested it yet so don't know if I have to catch window errors too.
Vue.config.errorHandler = function (error) {
//Toast.error(error.message)
console.warn(error.message)
//send error as event to google analytcs...
if (error) message = error.stack;
ga('send', 'event', 'Vue.config.errorHandler', message, navigator.userAgent);
}
window.onerror = function(message, source, lineno, colno, error) {
// maybe we need to also catch errors here and send to GA
}
But I found something like this too for typescript https://github.com/enkot/catch-decorator
While there is still no firebase crashlytics for web, google offers Stackdriver with error reporting functionality - it keeps track of all errors with ability to mark them as resolved (it can also send email notifications about new errors):
You can access it using the below url (make sure to put your firebase {project_id} in the link before clicking it):
https://console.cloud.google.com/errors?project={project_id}
There are two ways on how to use it:
Easy way, limited flexibility.
Every console.error(new Error(...)) reported from your firebase function is automatically tracked in the Stackdriver error logging platform.
So you just need to send an error report from your web app to your firebase function and log it using console.error inside that function.
Note, only an instances of Error object will be sent to the Stackdriver platform. For example console.error("{field1: 'text'}") won't be sent to Stackdriver. More info on that in this doc
More comprehensive way that provides an additional control (you can also report userId, your custom platform name, it's version, user agent, etc):
Here is a quick snippet on how it can be used (in our case we first send the error log from web app to our server and then report the error to Stackdriver):
in firebase nodejs:
const {ErrorReporting} = require('#google-cloud/error-reporting');
let serviceAccount = {...} //service account is your firebase credetials that holds your secret keys etc. See below for more details.
let config = {
projectId: serviceAccount.project_id,
reportMode: "always",
credentials: serviceAccount
}
let errors = new ErrorReporting(config);
Report error to Stackdriver from nodejs:
async function reportError(message){
//message is a string that contains the error name with an optional
//stacktrace as a string representing each stack frame separated using "\n".
//For example:
//message = "Error: Oh-hoh\n at MyClass.myMethod (filename.js:12:23)\n etc.etc."
const errorEvent = this.errors.event()
.setMessage(message)
.setUser(userId)
.setServiceContext("web-app", "1.0.0")
await errors.report(errorEvent)
}
More info about the Stackdriver library is available in this doc. And more info about the stacktrace and it's format can be found in the docs here
A few notes on setting it up:
You need to enable two things:
Enable Stackdrive api for your project using the link below (make sure to set your firebase {project_id} in the url below before clicking it)
https://console.developers.google.com/apis/library/clouderrorreporting.googleapis.com?project={project_id}
Make sure to also grant "Error writer" permission to the firebase service account so Stackdriver can receive the error logs (service account is a sort of representation of a "user" for your firebase project who accesses the services)
To grant the premission, follow the below steps:
first locate the "Firebase service account" using your firebase dashboard link (you can find it below) and remember it's value - it looks something like firebase-adminsdk-{random_symbols}#{project_id}.iam.gserviceaccount.com
Then open gcloud console under "Access"->"IAM". Or use the following link:
https://console.cloud.google.com/access/iam?project={project_id} <- put your firebase project id here
Locate your Firebase service account from the step 1.
Press edit for that account and add "Errors writer" permission:
Where to find the serviceAccount.json:
Regarding the serviceAccount - this is a universal credentials that can be used to authenticate many google services including the Stackdriver. You can obtain yours from your firebase dashboard using the url below (just put your firebase project_id in the link before using it):
https://console.firebase.google.com/u/0/project/{project_id}/settings/serviceaccounts/adminsdk
Open it and click "generate new credentials". This will generate a new service account and download the serviceAccount.json that you need to keep safe (you won't be able to get it again unless you generate a new one).
Apparently Sentry now supports several web frameworks out of the box.
I have recently integrated Sentry crashlytics for Django App.
see here:
https://sentry.io/platforms/

Appcelerator Google SignIn using module Ti.GoogleSignIn

Using Ti.GoogleSignIn module by Hansemann, i am trying to access my google drive. Problem is that the google does not honour the token i am getting from module and i am getting Error 401 : Unauthorized Invalid credentials.
On the other hand, if i use the token from Google developer playground, it works as expected.
I am setting the scope in the following way
Google.initialize({
clientID : "***********************************************.apps.googleusercontent.com",
scope : ['https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.appdata', 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive.metadata'] // Scope
});
So when using a clientID from the playground, it works in your app? Then your current setup may be incorrect. As the error seems to be thrown for both the Titanium based version and native version (bubbled up), you may receive some more help from the native community as well.

Resources