Custom OAuth getting 'loginWithService is not a function'


I copied ‘google’ and ‘accounts-google’ to my local packages directory and made a few changes to make it compatible with cisco spark as an oauth provider.

It was working great, so I thought I would share my success and publish ‘ciscospark’ and ‘accounts-ciscospark’

So I renamed all references, filenames, packages, etc and reset my meteor project.

Unlike ‘loginWithGoogle’ that is clearly published as an available function here:<ExternalService>

I’m using a custom service, which I would assume would work the same, ie loginWithCiscoSpark.

Heres the relevant code.

Meteor.loginWithCiscoSpark = function(options, callback) { … }

CiscoSpark = {};
OAuth.registerService(‘ciscospark’, 2, null, function(query)

CiscoSpark = {};
var config = ServiceConfiguration.configurations.findOne({service: ‘ciscospark’});
loginService: “ciscospark”,
loginStyle: loginStyle,
loginUrl: loginUrl,
credentialRequestCompleteCallback: credentialRequestCompleteCallback,
credentialToken: credentialToken,
popupOptions: { height: 600 }

{ service: “ciscospark” },
{ $set: {
loginStyle: ‘popup’,
clientId: ‘redacted’,
secret: ‘redacted’
{ upsert: true }


I wrote a guide a while ago for creating a custom Oauth service. If it will add any clarity, please check it out.


@robfallows I used your guide to create an implementation for Auth0, worked quite well, so thank you! :smiley:

@levensailor can you share your callback function in OAuth.registerService?


so the problem was that it needed to call loginWithCiscospark not loginWithCiscoSpark
the meteor code capitalizes the servicename ciscospark to Ciscospark.

Your guide was awesome @robfallows it was another where I read upperCamelCase was required.

this is described here:
‘click .login-button’: function () {
var serviceName =;

// XXX Service providers should be able to specify their
// `Meteor.loginWithX` method name.
var loginWithService = Meteor["loginWith" +
                              (serviceName === 'meteor-developer' ?
                               'MeteorDeveloperAccount' :

var options = {}; // use default scope unless specified
if (Accounts.ui._options.requestPermissions[serviceName])
  options.requestPermissions = Accounts.ui._options.requestPermissions[serviceName];
if (Accounts.ui._options.requestOfflineToken[serviceName])
  options.requestOfflineToken = Accounts.ui._options.requestOfflineToken[serviceName];
if (Accounts.ui._options.forceApprovalPrompt[serviceName])
  options.forceApprovalPrompt = Accounts.ui._options.forceApprovalPrompt[serviceName];

loginWithService(options, function (err) {
  loginResultCallback(serviceName, err);



Where to go from here…

So I know the oAuth flow works because I got an auth token and I can use it to pull my own display name and console it out. I’m doing that in the ciscospark_server.js

var identity = getIdentity(accessToken);

Two things i’m stuck on:

  1. the window doesn’t close using popup loginStyle.
  2. Is there a best practice to linking the oAuth service user fields to the local users database? I would imagine an upsert just mapping what i need? I’m strictly using this one service so its really a single sign on.

  1. I was using localhost instead of my root_url in the browser so it didn’t know how to close. fixed

  2. where else would the oauth values get inserted into the database if not getIdentity?