I'm using passport to authenticate users for my application using Facebook.
In my application, I have 2 different users: customers and professionals (transitioning to "experts").
I followed the Loopback docs to implement the loopback-component-passport package and passport-facebook and have it working for my customers.
Because I use custom User models, I followed this SO Post on how to get that fixed (note: I still use the build-in AccessToken model).
Angular Frontend
I use an Angular frontend. To redirect the user back to my frontend, I created a bootscript that looks like this:
'use strict';
module.exports = function(app) {
var router = app.loopback.Router();
var cookieParser = require('cookie');
// Redirect user to page set in env.APP_HOST
router.get('/auth/customer/success', function(req, res, next) {
const cookie = req.headers.cookie;
var result = cookieParser.parse(cookie);
res.redirect(process.env.APP_HOST + '/auth/facebook/?token=' +
result['access_token'] + '&id=' + result['userId'] +
'&err=&fbsr=');
});
router.get('/auth/expert/success', function(req, res, next) {
const cookie = req.headers.cookie;
var result = cookieParser.parse(cookie);
res.redirect(process.env.APP_HOST + '/expert/auth/facebook/?token='
+ result['access_token'] + '&id=' + result['userId'] +
'&err=&fbsr=');
});
app.use(router);
};
When I authenticate as a customer, I should be redirected to https://example.com/auth/customer/success
When I authenticate as a professional/expert, I should be redirected to https://example.com/auth/expert/success.
Setup a second passport-facebook
I have to load the configuration for both the customer and professional/expert which I'm doing in server.js. I created 2 providers.json files (providers.customer.json and provider.professional.json) containing their specific info.
This is how I load both configurations (perhaps a little messy):
var passportCustomer = require('loopback-component-passport');
var PassportConfiguratorCustomer = passportCustomer.PassportConfigurator;
var passportConfiguratorCustomer = new PassportConfiguratorCustomer(app);
var passportProfessional = require('loopback-component-passport');
var PassportConfiguratorProfessional = passportProfessional.PassportConfigurator;
var passportConfiguratorProfessional = new PassportConfiguratorProfessional(app);
// Setup passport configuration
var passportCustomerConfig = {};
var passportProfessionalConfig = {};
try {
passportCustomerConfig = require('./providers.customer.json');
passportProfessionalConfig = require('./providers.professional.json');
} catch(err) {
console.log('Please configure the passport strategy in providers.customer.json');
console.error(err);
process.exit(1); // Fatal error
}
// Init passport for customer
passportConfiguratorCustomer.init(false);
passportConfiguratorProfessional.init(false);
// Setup passport models
passportConfiguratorCustomer.setupModels({
userModel: app.models.Customer,
userIdentityModel: app.models.UserIdentityCustomer,
userCredentialModel: app.models.UserCredentialsCustomer
});
passportConfiguratorProfessional.setupModels({
userModel: app.models.Professional,
userIdentityModel: app.models.UserIdentityProfessional,
userCredentialModel: app.models.UserCredentialsProfessional
});
// Configure passport for customer
for(var s in passportCustomerConfig) {
var c = passportCustomerConfig[s];
c.session = c.session !== false;
passportConfiguratorCustomer.configureProvider(s, c);
}
// Configure passport for professional/expert
for(var s in passportProfessionalConfig) {
var c = passportProfessionalConfig[s];
c.session = c.session !== false;
// passportConfiguratorProfessional.configureProvider(s, c);
passportConfiguratorCustomer.configureProvider(s, c);
}
The actual problem
I have 2 different apps in Facebook (1 for customers, 1 for professionals/experts). When I authenticate using localhost:3000/auth/customer/facebook or localhost:3000/auth/expert/facebook I see that both apps are used for the correct endpoint. But no matter what endpoint I use, after authentication I'm always redirected to http://example.com/expert/auth/facebook
So my question is: How can I fix this issue so that customers are redirected to the customer endpoint and experts/professionals are redirected to their expert endpoint?
Additional information
Registration works fine, I can find customers in customer table and expert in expert table in my database
For reference: providers.customer.json
{
"facebook-login": {
"provider": "facebook",
"module": "passport-facebook",
"clientID": "OhOh, I removed it :)",
"clientSecret": "Supa Dupa secret",
"callbackURL": "/auth/customer/facebook/callback",
"authPath": "/auth/customer/facebook",
"callbackPath": "/auth/customer/facebook/callback",
"successRedirect": "/auth/customer/success",
"failureRedirect": "/auth/customer/failure",
"scope": ["email"],
"failureFlash": true,
"profileFields" : ["locale", "name", "email"]
},
"facebook-link": {
"provider": "facebook",
"module": "passport-facebook",
"clientID": "OhOh, I removed it :)",
"clientSecret": "Supa Dupa secret",
"callbackURL": "/link/customer/facebook/callback",
"authPath": "/link/customer/facebook",
"callbackPath": "/link/customer/facebook/callback",
"successRedirect": "/auth/customer/success",
"failureRedirect": "/auth/customer/failure",
"scope": ["email"],
"link": true,
"failureFlash": true
}
}
For reference: providers.professional.json
{
"facebook-login": {
"provider": "facebook",
"module": "passport-facebook",
"clientID": "Aaaaand",
"clientSecret": "It's gone",
"callbackURL": "/auth/expert/facebook/callback",
"authPath": "/auth/expert/facebook",
"callbackPath": "/auth/expert/facebook/callback",
"successRedirect": "/auth/expert/success",
"failureRedirect": "/auth/expert/failure",
"scope": ["email"],
"failureFlash": true,
"profileFields" : ["locale", "name", "email"]
},
"facebook-link": {
"provider": "facebook",
"module": "passport-facebook",
"clientID": "Aaaaand",
"clientSecret": "It's gone",
"callbackURL": "/link/expert/facebook/callback",
"authPath": "/link/expert/facebook",
"callbackPath": "/link/expert/facebook/callback",
"successRedirect": "/auth/expert/success",
"failureRedirect": "/auth/expert/failure",
"scope": ["email"],
"link": true,
"failureFlash": true
}
}
So I was able to fix this by using the PassPortConfigurator#configureProvider method. Instead of using the JSON files to setup the facebook authentication, I did it in JS.
var passportCustomer = require('loopback-component-passport');
var PassportConfiguratorCustomer = passportCustomer.PassportConfigurator;
var passportConfiguratorCustomer = new PassportConfiguratorCustomer(app); // Note the first letter is not a capital one
// Init passport for customer
passportConfiguratorCustomer.init(false);
// Setup passport models
passportConfiguratorCustomer.setupModels({
userModel: app.models.Customer,
userIdentityModel: app.models.UserIdentityCustomer,
userCredentialModel: app.models.UserCredentialsCustomer
});
// Load configuration here instead of the JSON file.
passportConfiguratorProfessional.configureProvider('facebook-login-expert', {
module: 'passport-facebook',
clientID: XXX,
clientSecret: XXX,
callbackURL: '/auth/expert/facebook/callback',
authPath: '/auth/expert/facebook',
callbackPath: '/auth/expert/facebook/callback',
successRedirect: '/auth/expert/success',
failureRedirect: '/auth/expert/failure',
scope: ['email'],
failureFlash: true,
profileFields: ['locale', 'name', 'email']
});
Related
I am trying to create an online meeting and recover its URL like explained here in the docs, but when the request is run I get this error:
{
"statusCode": 400,
"code": "AuthenticationError",
"message": "Error authenticating with resource",
"requestId": "652ea3be-6a97-47e8-bfc6-3d7d1d51d425",
"date": "2020-09-01T12:53:41.000Z",
"body": "{
"code":"AuthenticationError",
"message":"Error authenticating with resource",
"innerError":{
"date":"2020-09-01T13:53:41",
"request-id":"652ea3be-6a97-47e8-bfc6-3d7d1d51d425"
}
}"
}
I tried also the get started projet for JS and it's working fine so I can't spot the problem.
here is what I used:
const msalConfig = {
auth: {
clientId: 'my_app_id',
redirectUri: 'http://localhost:8080'
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
forceRefresh: false
}
};
const loginRequest = { scopes: [
'openid',
'profile',
'user.read',
'calendars.read',
'User.Read.All',
'User.Export.All'
]
}
const options = new MicrosoftGraph.MSALAuthenticationProviderOptions([
'user.read',
'calendars.read',
'OnlineMeetings.ReadWrite'
]);
const onlineMeeting = {
startDateTime:"2020-09-01T16:00:34.2444915-07:00",
endDateTime:"2020-09-01T16:30:34.2464912-07:00",
subject:"test meeting"
};
const authProvider = new MicrosoftGraph.ImplicitMSALAuthenticationProvider(msalClient, options);
// Initialize the Graph client
const graphClient = MicrosoftGraph.Client.initWithMiddleware({authProvider});
// then I call this inside an async function
let events = await graphClient.api('/users/my_UserPrincipalName/onlineMeetings').post(onlineMeeting);
//let events = await graphClient.api('/me/onlineMeetings').post(onlineMeeting);
// I tried with both calls and none of them worked
and here are the permissions on azure active directory:
So any ideas on how to solve this ?
thanks
You didn't provide a correct access token.
Since Create onlineMeeting only supports Delegated (work or school account) permission type, you need to get the access token with Auth code flow or Implicit flow.
The started project for JS is using Implicit flow. So you can use Implicit flow to get the access token.
Here is the example in Postman:
The Auth URL above is https://login.microsoftonline.com/{your tenant}/oauth2/v2.0/authorize.
I figured out how to make it work in my code:
let's call my user, which I used all this time, user "A", all I did is that I simply created another user "B" in Azure Active Directory and then logging in with this new user "B" in the login screen instead of the admin user "A" that I used before..... and now it's working.
But this does not explain the issue, so if anyone can explain the difference or why it didn't work with the first account, that would be very helpful.
I have the career PersistedModel for storing the data in the database and i have the attachment model for file storage to store in some location.Now i want to send an email with the data. I can able to send only the career data but i want to send attachment also with the same email.I could not able to fetch the file name because it is not in the career model it is in the attachment. How to do get the file name and send it help me out.
career.js
const app = require('../../server/server');
module.exports = function(Career) {
Career.afterRemote('create', function(context, remoteMethodOutput, next) {
next();
console.log(remoteMethodOutput)
Career.app.models.Email.send({
to: 'lakshmipriya.l#gmail.com',
from: 'lakshmipriya.l#gmail.com',
subject: 'my subject',
html: 'Hello-world',
attachments: [
{
path: '../files/resume/'+remoteMethodOutput.resume,
}
],
}, function(err, mail) {
// console.log(context.result.email)
console.log('email sent!');
cb(err);
});
});
};
attachment.json
{
"name": "attachment",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
My project structure where i used to store the files is
Using absolute path for your files is always more robust than relative path. Use __dirname for that :
const filePath = __dirname + '/files/resume/' + remoteMethodOutput.resume;
If you need to go up one level, then enter the files directory, you need Node's path module to resolve it :
const path = require("path"),
filePath = path.normalize(__dirname + '/../files/resume/' + remoteMethodOutput.resume)
The AWS documentation indicates that it is possible for an admin to create a user pool user in AWS Cognito using the API.
Here is the documentation I am referring to: https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html
However the documentation provides scant details and not even an example of how this is done. It makes no mention of what endpoint to call, what SDK function to use, or anything regarding authentication, etc.
Does anyone have experience creating new users directly from your code ?
It's actually quite easy if you follow the development documentation (https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html), more specifically the "signUp" function.
From the Docs:
var params = {
ClientId: 'STRING_VALUE', /* required */
Password: 'STRING_VALUE', /* required */
Username: 'STRING_VALUE', /* required */
AnalyticsMetadata: {
AnalyticsEndpointId: 'STRING_VALUE'
},
SecretHash: 'STRING_VALUE',
UserAttributes: [
{
Name: 'STRING_VALUE', /* required */
Value: 'STRING_VALUE'
},
/* more items */
],
UserContextData: {
EncodedData: 'STRING_VALUE'
},
ValidationData: [
{
Name: 'STRING_VALUE', /* required */
Value: 'STRING_VALUE'
},
/* more items */
]
};
cognitoidentityserviceprovider.signUp(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
And using this, it's simple to create a user (example in Lambda, but can easily be modified as JS on its own):
'use strict'
var AWS = require('aws-sdk');
var resp200ok = { statusCode: 200, headers: {'Content-Type': 'application/json'}, body: {} };
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
// ^ Hard to find that this is the way to import the library, but it was obvious in docs
exports.handler = function(event, context, callback){
var params = {
ClientId: 'the App Client you set up with your identity pool (usually 26 alphanum chars)',
Password: 'the password you want the user to have (keep in mind the password restrictions you set when creating pool)',
Username: 'the username you want the user to have',
UserAttributes:[ {
{
Name: 'name',
Value: 'Private'
},
{
Name: 'family_name',
Value: 'Not-Tellinglol'
},
}],
};
cognitoidentityserviceprovider.signUp(params, function(err, data) {
if (err){ console.log(err, err.stack); }
else{ resp200ok.body = JSON.stringify(data); callback(null, resp200ok); }
});
};
Anything you set to required in your Cognito pool setup has to be in the UserAttributes section (usually the email is defaulted to required, check if yours is). The list of things you can assign values to is found in (Cognito pool) General Settings -> App Clients -> Show Details -> Set Read/Write -> (list of things), here you can add custom attributes (like if you want to specify what city your user is from, or if you want to add whatever else (String/Number)).
When assigning a value to a custom field, your "Name" in the UserAttributes will be "custom:whatever", so if the custom field is "city" the Name is "custom:city".
Hopefully I wasn't stating too much of the obvious, but these are things it took me a while to figure out with the broken up SO info, and AWS docs, and I figured I'd plop it all together.
Here is an example using python/Flask
import traceback
import boto3
from flask import Flask, render_template, request
app = Flask(__name__)
def cognito_register_user(email):
print("sign up user: ", email)
try:
aws_client = boto3.client('cognito-idp', region_name = "us-west-2",)
response = aws_client.admin_create_user(UserPoolId="us-west-2_sdfgsdfgsdfg",Username=email,UserAttributes=[{"Name": "email","Value": email},{ "Name": "email_verified", "Value": "true" }],DesiredDeliveryMediums=['EMAIL'])
print("response=", response)
return response
except:
traceback.print_exc()
return None
#app.route('/')
def root():
return render_template('register_email.html', title='register mail')
#app.route('/register/email', methods=['POST'])
def sign_up():
if request.method == 'POST':
email = request.form['email']
print("email=", email)
cognito_register_user(email)
return render_template('register_email_complete.html', title='flask test', email=email)
if __name__ == "__main__":
app.run(debug=True)
My web app allows signing up / signing in with a Google account. I am using the following code to obtain user info from Google:
var scopes = ['profile', 'email'];
var url = oauth2Client.generateAuthUrl({ access_type: 'offline', scope: scopes });
router.route('/authorize').post((req, res) => {
code = req.body.code;
oauth2Client.getToken(code, (err, tokens) => {
if (err) return // error handler
oauth2Client.verifyIdToken(tokens.id_token, clientId, (err, login) => {
if (err) return // error handler
console.log(login.getPayload()); // this gives me the JSON object below
});
});
});
I've tried adding different scopes, but I always just get the same info, which doesn't include the user's real name:
{ azp: 'stuffblahblah',
aud: 'stuffblahblah',
sub: 'google-id-here',
email: 'email#address.com',
email_verified: true,
at_hash: 'some-hash',
iss: 'accounts.google.com',
iat: 1234567890,
exp: 1234567890 }
Despite some documentation suggesting it's possible to get info like real name in the id_token (see https://developers.google.com/identity/sign-in/android/backend-auth), I couldn't get it to return that info with the .getToken method. However, I was able to get it by requesting the info in a separate request via the access token:
let url = 'https://www.googleapis.com/oauth2/v3/userinfo?access_token=' + access_token;
request(url, (err, response, body) => {
if (err) console.log('error');
console.log(body);
});
And the body looks like this:
{
"sub": "4319874317893142",
"name": "My Real name",
"given_name": "My First Name",
"family_name": "My Last Name",
"profile": "https://plus.google.com/link_to_my_profile",
"picture": "https://lh4.googleusercontent.com/link_to_my_pic.jpg",
"email": "email#address.com",
"email_verified": true,
"gender": "male",
"locale": "en"
}
Still wishing there was a way to grab the real name in my initial request, rather than having to make a separate one, but this works well enough.
I have a web ftp portal that was created a few years ago by a developer that is no longer around. The code for the website is written in Node.js. Inside of app.js is the following code:
var validUsers = [{
name:'x',
user:'907c78ef73998eafc2680e5fdd4798a8eef0881a',
pass:'95489cf3039eb2f5938e3daa954d04276bbf90e7',
dir:''
},{
name:'y',
user:'b26e5ebda152e81099ec78be2f9c191ee25e1cd6',
pass:'e3725873ae302e3f12eb97b02feb7457de9706c2',
dir:'y'
},{
name:'y2',
user:'3182b54d9f4d08641b5a9a0fb33f74df5d76b222',
pass:'916b2e1941c9e23610f8bd3462cdb19f55b5c631',
dir:'y2'
},{
name:'y3',
user:'38aa53de31c04bcfae9163cc23b7963ed9cf90f7',
pass:'7a98cf84c2c61a30f6c4e3984c0cad2eb29f5d6f',
dir:'y3'
},{
name:'y4',
user:'51e822c50cc62cdbdb850a439ea75b6d45ac487b',
pass:'da6a77293ddcdc7047dd461a94c88c8377753265',
dir:'y4'
},{
name:'y5',
user:'14ad0aca26e00f615990946181ee3405c6ede0f1',
pass:'4eb4e0e1ea0f04422b5bc6031ee37c8dc971236d',
dir:'y5'
},{
name:'y6',
user:'4ec9bdb28c5da0f9813e9eed55a0f1dc6217a305',
pass:'e72bd0bbd37423bb0c9b9edfb9ce94446161c511',
dir:'y6'
},{
name:'y7',
user:'f4603bd4ae9e4aa2a11d903d0b178b37a57b1bac',
pass:'8a6a67f235738c4b2e4f88d4608bdcf0bbc49f51',
dir:'y7'
},{
name:'Guest',
user:'35675e68f4b5af7b995d9205ad0fc43842f16450',
pass:'370bb444ef91a3999b1c36af97e166f18848e7b7',
dir:'Guest'
},{
name:'y8',
user:'d8f51fbf5e13e9f2637a8d5c4bd1ab251bd61c30',
pass:'1a047e6dd554ffdd67524916820a8fa23acd2c6e',
dir:'y8'
}];
The x and y1-8 are substitutions for the actual client names and corresponding directories. Example being the 'Guest' name and directory. My question is, the user and pass are hash values from crypto. Yet they result in specific usernames and passwords. If I wanted to reset a username or password, or add another. How would I figure out the corresponding hash value to add to the code based on the username/password strings I want to add.
Any input would be very helpful.
EDIT:
The rest of the FTP code:
app.get('/ftp/', function(req, res){
var pageName = 'File Transfer Portal';
var rNav = '',
sNav = '',
cNav = '',
imNav = '',
title = 'companyNameOmitted: '+pageName,
bodyClass = 'top ftp',
keywords = 'keywordsOmitted',
description = 'descriptionOmiited',
url = '/ftp/';
res.render('ftp', {
title: title,
bodyClass: bodyClass,
keywords: keywords,
description: description,
url: siteRoot+url,
pageEmail: 'mailto:?subject='+escape(title)+'&body='+escape(description)+'%0A'+siteRoot+url,
eUrl:escape(siteRoot+url),
eTitle:escape(title),
eDescription:escape(description),
rNav:rNav,
sNav:sNav,
cNav:cNav,
imNav:imNav});
//console.log(uniqId()+':'+pageName);
});
app.post('/ftp/upload', function(req, res){
//console.log(req.files);
var SID = req.cookies.SID;
var sessionUser = (users[SID]) ? users[SID] : false;
if (!!sessionUser){
_.each(req.files,function (file) {
console.log(new Date(curTime()).toGMTString()+' | Recieved '+file.name+' ('+file.size+' bytes) from '+sessionUser.name);
var newPath = __dirname + '/complete/'+_.where(validUsers,{user:sessionUser.user})[0].dir+'/'+file.name;
fs.rename(file.path,newPath,function(err) {
if (err) throw err;
else {
res.redirect('back');
if (sessionUser.name != 'adminOmitted') {
var htmlString = '<b>'+sessionUser.name+'</b> has uploaded a file <b>'+file.name+'</b>.<br /><br />View it on the File Transfer Portal.';
var transport = nodemailer.createTransport("SMTP",{
host: "hostname.com", // hostname
secureConnection: true, // use SSL
port: 465, // port for secure SMTP
auth: {
user: "user#host.com",
pass: "pass"
}
});
transport.sendMail({
sender:'sender#host.com',
to:'receiver#host.com',
subject:'File Upload: '+sessionUser.name+' uploaded '+file.name,
html: htmlString
},function(err) {
if (err) console.log(err);
else console.log('Notification Sent: S&A File Upload: '+sessionUser.name+' uploaded '+file.name);
});
}
}
});
And the login code...
app.get('/ftp/d/:hash/:filename', function(req, res){
var SID = req.cookies.SID;
var ip = req.ip;
//console.log(ip);
var sessionUser = (users[SID]) ? ((users[SID].md5==req.params.hash)&&(users[SID].ip==ip)) ? users[SID] : false : false;
if (sessionUser) {
var realpath = __dirname +'/complete/'+_.where(validUsers,{user:sessionUser.user})[0].dir+'/'+req.params.filename.replace('>','/');
console.log(new Date(curTime()).toGMTString()+' | Sending '+realpath.substr(realpath.indexOf('complete')+9)+' to '+sessionUser.name);
res.download(realpath,realpath.substr(realpath.lastIndexOf('/')+1),function(err){
if (err) {
res.redirect(302,'/ftp/');
throw (err);
}
});
} else {
console.log(new Date(curTime()).toGMTString()+' | Download request failed authorization for '+req.params.filename);
console.log(new Date(curTime()).toGMTString()+' | Hash: '+req.params.hash);
console.log(new Date(curTime()).toGMTString()+' | SID: '+req.cookies.SID);
res.redirect(302,'/ftp/');
}
});
sio.sockets.on('connection', function (socket) {
var SID = socket.handshake.SID;
if (!users[SID]) register(SID,socket.handshake.address.address);
//console.log(users);
socket.on('login',function(data) {
var thisUser = _.where(validUsers,{user:data.u,pass:data.p})[0];
if (_.isEmpty(thisUser)) {
if (!!users[SID].ip) {
console.log(new Date(curTime()).toGMTString()+' | '+users[SID].ip+' has failed logging in.');
console.log(new Date(curTime()).toGMTString()+' | '+'U:'+data.u);
console.log(new Date(curTime()).toGMTString()+' | '+'P:'+data.p);
}
socket.emit('login',{complete:false,name:false});
} else {
console.log(new Date(curTime()).toGMTString()+' | '+thisUser.name+' has logged in.');
users[SID].name = thisUser.name;
users[SID].user = thisUser.user;
socket.emit('login',{complete:true,name:thisUser.name});
}
});
And the disconnect function, the only code between the login and the disconnect functions are a move file and a delete file function which I doubt are of any use.
//console.log(users);
socket.on('disconnect',function() {
setTimeout(function() {
if (!!users[SID]) {
if (curTime()-users[SID].lastTap>30000)
unregister(SID);
else console.log('Not removing; connection still active. ('+users[SID].name+')');
} else (unregister(SID));
},30000);
});
});
and finally, the crypto functions:
function getMD5(string) {
return crypto.
createHash('md5').
update(string).
digest("hex");
}
function getSHA1(string) {
return crypto.
createHash('sha1').
update(string).
digest("hex");
}
I know the formatting isn't perfect, I've tried to keep it as neat as possible, I think that's all of the relevant functions. I doubt the .jade file for the FTP Portal would be of any use.
You can't.
The usernames and passwords have been put through an asymmetric encryption (ie MD5). This was likely done to protect the user's personal information if the server is hacked.
You're still missing the part of the code that handles the authentication and sets the session cookie.
If you can find the code that handles the auth and you know the username beforehand you could re-hash it to cross-reference the username to the entries list.
Otherwise, your only option is to crack the usernames/passwords which can be difficult/impossible depending on their complexity.
Good luck...