I'm trying to set the user-agent parameter in Selenium::Chrome, but am not finding the correct way. Has anyone successfully done this?
my $driver = Selenium::Chrome->new(
'user-agent' => 'TEST',
'--user-agent' => 'TEST',
'chromeOptions' => {
prefs => {
'user-agent' => 'TEST',
'--user-agent' => 'TEST',
},
},
extra_capabilities => {
'chromeOptions' => {
prefs => {
'user-agent' => 'TEST',
'--user-agent' => 'TEST',
},
},
'goog:chromeOptions' => {
prefs => {
'download.default_directory' => '/tmp',
'user-agent' => 'TEST',
'--user-agent' => 'TEST'
},
args => [ 'headless' ]
}
}
);
user-agent can be set through the custom_args argument.
To set the user-agent parameter in Selenium::Chrome you can use the following solution:
my $chrome = Selenium::Chrome->new(
custom_args => "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
);
PS: Ideally, you should pass a valid user-agent following What is my user agent?
Related
I have a fastify backend that runs graphql server. Without authentication hook at the server, my all graphql request and subscription in my vue app works fine.
Adding jwt authentication only graphql query and mutation works but my realtime subsciption keeps giving me unauthorized 401 error.
{"type":"UnauthorizedError","message":"No Authorization was found in request.headers","stack":"UnauthorizedError: No Authorization was found in request.headers\n at lookupToken
Theres an answer online saying to override wsclient with this code, but it does not resolve my issue.
wsClient.connectionParams = () => {
return {
headers: {
Authorization: localStorage.getItem(AUTH_TOKEN) ? `Bearer ${localStorage.getItem(AUTH_TOKEN)}` : ''
}
}
}
My Setup
vue-apollo.js
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { createApolloClient, restartWebsockets } from 'vue-cli-plugin-apollo/graphql-client';
// Name of the localStorage item
const AUTH_TOKEN = 'apollo-token';
// Http endpoint
const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:3000/graphql';
// Config
const defaultOptions = {
// You can use `https` for secure connection (recommended in production)
httpEndpoint,
// You can use `wss` for secure connection (recommended in production)
// Use `null` to disable subscriptions
wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:3000/graphql',
// LocalStorage token
tokenName: AUTH_TOKEN,
// Enable Automatic Query persisting with Apollo Engine
persisting: false,
// Use websockets for everything (no HTTP)
// You need to pass a `wsEndpoint` for this to work
websocketsOnly: false,
// Is being rendered on the server?
ssr: false,
// Override default apollo link
// note: don't override httpLink here, specify httpLink options in the
// httpLinkOptions property of defaultOptions.
// link: myLink
// Override default cache
// cache: myCache
// Override the way the Authorization header is set
// getAuth: tokenName => {
// const token = 'Bearer ' + localStorage.getItem(AUTH_TOKEN);
// return token || '';
// },
// Additional ApolloClient options
// apollo: { ... }
// Client local data (see apollo-link-state)
// clientState: { resolvers: { ... }, defaults: { ... } }
};
// Call this in the Vue app file
export function createProvider(options = {}) {
// Create apollo client
const { apolloClient, wsClient } = createApolloClient({
...defaultOptions,
//...options,
});
wsClient.connectionParams = () => {
return {
headers: {
authorization: localStorage.getItem('apollo-token'),
},
};
};
apolloClient.wsClient = wsClient;
// Create vue apollo provider
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
defaultOptions: {
$query: {
fetchPolicy: 'cache-and-network',
},
},
errorHandler(error) {
// eslint-disable-next-line no-console
console.log(
'%cError',
'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;',
error.message
);
},
});
return apolloProvider;
}
// Manually call this when user log in
export async function onLogin(apolloClient, token) {
if (typeof localStorage !== 'undefined' && token) {
localStorage.setItem(AUTH_TOKEN, token);
}
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
try {
await apolloClient.resetStore();
} catch (e) {
// eslint-disable-next-line no-console
console.log('%cError on cache reset (login)', 'color: orange;', e.message);
}
}
// Manually call this when user log out
export async function onLogout(apolloClient) {
if (typeof localStorage !== 'undefined') {
localStorage.removeItem(AUTH_TOKEN);
}
if (apolloClient.wsClient) restartWebsockets(apolloClient.wsClient);
try {
await apolloClient.resetStore();
} catch (e) {
// eslint-disable-next-line no-console
console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
}
{
console.log('%cError on cache reset (logout)', 'color: orange;', e.message);
}
}
// Install the vue plugin
Vue.use(VueApollo);
SERVER RESPONSES
When I console log the queries or mutations
{
host: 'localhost:3000',
connection: 'keep-alive',
'content-length': '205',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"',
accept: '*/*',
'content-type': 'application/json',
authorization: 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlJiQ2RxSzIwMm1URmx5NzY4X1VMWSJ9.eyJpc3MiOiJodHRwczovL2Rldi01M3c3NXJ3Yi5hdS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI0NjQ0YWIyM2M0NjMwMDcwNTE0ZTY0IiwiYXVkIjpbImh0dHBzOi8vYXBpLmd1YXJkZXguY28ubnovIiwiaHR0cHM6Ly9kZXYtNTN3NzVyd2IuYXUuYXV0aDAuY29tL3VzIHByb2ZpbGUgZW1haWwifQ.e8OJDXmICjo582blGuCOCKtYOsrRcQrG8qp_ABcFqg6faMkw0xJNbJ3r0vvktBSjN9Kp93cIHlEr_ljSpZyb9roJbCShE7LXageX3wgvtq_nawQLOMTn-aC6AQqELjvgIEsuPb998hXioF0bXljdLnUy3Fi71cZby2uciqJes7iU2j5K2VuqGNLytNJc_RL9Cin7Z_7EE5J4_Djql1jtfN7boCrAMxjRIhs2EgQ_Y0DSr53WkdssBDcKfK1fk_cxksRXRFxhbKfrJSAWIdrGf6_hlVL8WdOYRNSlzi79_x0wNPGA0zzuEX458x0ffqXvBgnb7DUC_AsT2028e1tY',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
origin: 'http://localhost:8080',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:8080/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9'
}
When I console log the subscription headers I get:
{
host: 'localhost:3000',
connection: 'Upgrade',
pragma: 'no-cache',
'cache-control': 'no-cache',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
upgrade: 'websocket',
origin: 'http://localhost:8080',
'sec-websocket-version': '13',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
cookie: '_legacy_auth.SECRECT.is.authenticated=true; auth.is.authenticated=true',
'sec-websocket-key': 'iFNve3jfWvxmJRCsrEH+Og==',
'sec-websocket-extensions': 'permessage-deflate; client_max_window_bits',
'sec-websocket-protocol': 'graphql-ws'
}
Could you help to solve the problem in API testing by Cypress. When I set the request headers in options section Cypress ignores them and replaces with default ones.
The example of my request:
cy.request({
method: 'POST',
url: 'https://orion.koto.com/api/inn',
Headers: {'sid':'21102xiXXdvsfykg5pj'},
body:'["3211455115"]' ,
})
the request sent by Cypress:
Method: POST URL: https://orion.koto.com/api/inn Headers: {
"Connection": "keep-alive", "user-agent": "Mozilla/5.0 (Windows NT
10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36", "accept": "/",
"accept-encoding": "gzip, deflate", "content-length": 14 } Body:
["3211455115"]
const green_value = "TOTO"
describe('As I have set a green header',()=>{
it('should use this header',()=>{
cy.visit({
method: 'GET',
url: 'https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending',
headers: {
'green': green_value
}
})
})
})
On my side, it work with visit() function. The url used will show you header sent.
Hope this code sample can help you to implement request() function.
Revising this question as I have made some progress and passport-twitter authentication is working mostly: VueJS app with Express/Knex/Postgresql backend.
The problem is that I am combining passport-twitter with my previous usage of passport-local using jwt. As a result, I have to generate a header token for the new Twitter user. Currently on logging in with Twitter, the header token is not being read. Without a valid token the app does crazy, time consuming things.
here is the header object from the initial Twitter login request, showing token as an undefined Object:
headers:
{ host: 'localhost:8000',
connection: 'keep-alive',
accept: 'application/json, text/plain, */*',
origin: 'http://localhost:8080',
'user-agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
token: '[object Object]',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
referer:
'http://localhost:8080/?user=%7B%22id%22%3A10,%22email%22%3Anull,%22token%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6bnVsbCwiaWQiOjEwLCJleHAiOjE1NzYwNTU1MzYsImlhdCI6MTU3MDg2NzkzNn0.SUYL2KcnK8C9zYNLCcqGF99TjfIRxAcyg0Uc8WjQJD0%22%7D',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'if-none-match': 'W/"79-a0G25cV4V6cfQoTIFr1X/nYU2Kg"' },
On refreshing the browser, the header token appears as expected and errors are gone.
headers:
{ host: 'localhost:8000',
connection: 'keep-alive',
accept: 'application/json, text/plain, */*',
origin: 'http://localhost:8080',
'user-agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
token:
'Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6bnVsbCwiaWQiOjEwLCJleHAiOjE1NzYwNTU1MzYsImlhdCI6MTU3MDg2NzkzNn0.SUYL2KcnK8C9zYNLCcqGF99TjfIRxAcyg0Uc8WjQJD0',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
referer:
'http://localhost:8080/?user=%7B%22id%22%3A10,%22email%22%3Anull,%22token%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6bnVsbCwiaWQiOjEwLCJleHAiOjE1NzYwNTU1MzYsImlhdCI6MTU3MDg2NzkzNn0.SUYL2KcnK8C9zYNLCcqGF99TjfIRxAcyg0Uc8WjQJD0%22%7D',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'if-none-match': 'W/"79-a0G25cV4V6cfQoTIFr1X/nYU2Kg"' }
Here are the relevant files in Express:
authenticate.js is middleware, I am using to get the token from the header:
const jwt = require('express-jwt');
const getTokenFromHeaders = (req) => {
console.log('req from headers is: ', req)
const { headers: { token } } = req; // same as token = req.headers.token
if(token && token.split(' ')[0] === 'Token') {
return token.split(' ')[1];
}
return null;
};
const auth = {
required: jwt({
secret: 'secret',
userProperty: 'user',
getToken: getTokenFromHeaders,
}),
optional: jwt({
secret: 'secret',
userProperty: 'user',
getToken: getTokenFromHeaders,
credentialsRequired: false,
}),
};
module.exports = auth;
app.js:
const express = require('express')
const bodyParser = require('body-parser')
const path = require('path')
const dotenv = require('dotenv')
const Knex = require('knex')
const { Model } = require('objection')
const cors = require('cors');
const pathfinderUI = require('pathfinder-ui');
const session = require('express-session');
const passport = require('passport')
dotenv.config()
const app = express()
// objection setup
const knexfile = require('../knexfile')
const knex = Knex(knexfile[process.env.NODE_ENV])
Model.knex(knex)
//Configure our app
app.use('/pathfinder', function (req, res, next) {
pathfinderUI(app)
next()
}, pathfinderUI.router);
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.use(cors(corsOptions));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var sess = {
secret: 'keyboard cat',
cookie: {}
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
}
app.use(session(sess))
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport');
// api routes
// should we refactor this?
app.use("/api/auth", require("./routes/auth"))
app.use("/api/posts", require("./routes/posts"))
app.use("/api/acts", require("./routes/acts"))
app.use("/api/reports", require("./routes/reports"))
app.use("/api/groups", require("./routes/groups"))
app.use("/api/users", require("./routes/users"))
app.use("/api/memberships", require("./routes/memberships"))
app.use("/api/kudos", require("./routes/kudos"))
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "index.html"))
})
module.exports = app
passport.js:
const passport = require('passport');
const LocalStrategy = require('passport-local');
const TwitterStrategy = require('passport-twitter').Strategy
const authHelpers = require('../auth/helpers');
var port = process.env.PORT || 8000;
const User = require('../models/User');
var trustProxy = false;
if (process.env.DYNO) {
// Apps on heroku are behind a trusted proxy
trustProxy = true;
}
passport.use(new LocalStrategy({
usernameField: 'user[email]',
passwordField: 'user[password]',
}, async (email, password, done) => {
const user = await User.query().where('email', email );
if (user && user.length === 1 && authHelpers.comparePass(password, user[0].password)) {
return done(null, user[0]);
} else {
return done(null, false, { errors: { 'email or password': 'is invalid' } });
}
}));
passport.use(new TwitterStrategy({
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_SECRET_KEY,
callbackURL: process.env.TWITTER_CALLBACK_URL, //this will need to be dealt with
proxy: trustProxy
}, async function(token, tokenSecret, profile, done) {
let user = await User.query().findOne({twitter_id: profile.id_str})
console.log('hitting the passport twitter strategy')
if (user) {
// todo: update user with twitter profile
return done(null, user);
} else {
user = await authHelpers.createTwitterUser(profile);
console.log("The User from createTwitterUser is " + user);
return done(null, user);
}
}));
auth.js:
const express = require('express');
const User = require('../models/User');
const auth = require('../middlewares/authenticate');
const passport = require('passport');
const authHelpers = require('../auth/helpers')
let router = express.Router();
...
router.get('/twitter',
passport.authenticate('twitter')
);
router.get('/twitter/callback',
passport.authenticate('twitter', { failureRedirect: process.env.VUE_LOGIN_URL}),
function(req, res) {
// Successful authentication, redirect home.
const user = JSON.stringify(req.user);
console.log('hittingthe callback routesending stringified user: ', user);
res.redirect(process.env.VUE_HOME_URL + '?user=' + user);
});
module.exports = router;
helpers.js:
const bcrypt = require('bcryptjs');
const User = require('../models/User');
const jwt = require('jsonwebtoken');
...
async function createTwitterUser(profile) {
let newUser = await User.query()
.insert({
username: profile.screen_name,
bio: profile.description,
location: profile.location,
avatar: profile.profile_image_url_https,
twitter_id: profile.id_str //change to int
})
.returning('*');
console.log("new User is: ", newUser);
return newUser;
}
...
module.exports = {
comparePass,
createUser,
toAuthJSON
};
I don't understand why express js cannot read my header.
I use vuejs + axios for send data.
I use a module for intercept request ans response for send token.
In axios module :
axios.interceptors.request.use((req) => {
req.headers.authorization = `Bearer: ${MYTOKEN}`;
return req;
});
In my server, i use nodesJS + Express with middleware :
const router = express.Router();
router.use(function timeLog(req, res, next) {
console.log(req.headers.authorization); // undefined :(
})
So req.headers do not contains key 'authorization' and console.log(req.headers.authorization); return to me 'UNDEFINED'.
I've try to put req.header.BLABLABLA. I find it but not as key.
I really don't understand.
Exemple of return with authorization :
{ host: 'localhost:5000',
connection: 'keep-alive',
'access-control-request-method': 'POST',
origin: 'http://localhost:8080',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
'access-control-request-headers': 'authorization,content-type',
accept: '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'fr-FR,fr;q=0.9,en;q=0.8,en-US;q=0.7,ru;q=0.6'
}
try this
axios.interceptors.request.use((req) => {
// req here, it's axios config, not express req'. req.headers.Authorization = Bearer: ${MYTOKEN}`;
return req;
});
Authorization => start with A Capital
You're using Axios in the wrong way.
You're trying to log headers of the Express Request, not headers of the Axios.
// server/index.js
router.use(function timeLog(req, res, next) {
console.log(req.headers.authorization); // of course this is will undefined
})
If you're doing like so, you'll get your authorization headers...
// server/index.js
import axios from 'axios'
axios.interceptors.request.use((req) => {
// `req` here, it's axios config, not express `req'.
req.headers.authorization = `Bearer: ${MYTOKEN}`;
return req;
});
router.use(function timeLog(req, res, next) {
console.log(axios.headers.authorization); // here we are
})
Trying to get into https://www.germaniasport.hr/hr/kladjenje/ponuda using casperjs 1.1.4 phantomjs 1.9.8, but can't find what protection is using this website. Tried with ip adress, tried casperjs --ssl-protocol=tlsv1, casperjs --ssl-protocol=any - but no results.
var casper = require('casper').create(
{
pageSettings:
{
loadImages: false,
loadPlugins: false,
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
},
verbose: false,
logLevel: "debug",
viewportSize : { width: 1920, height: 1080 }
});
casper.start('https://91.213.84.25/hr/kladjenje/ponuda', function() {
this.wait(5000);
this.capture("sh.jpg");
});
You are missing casper.run();at the end of your code, so your code never actually runs...