I have an Azure hosted App when I try to cy.visit('url') Cypress stuck and below is visible.
After sometime "HTTP Error 414. The request URL is too long." is visible.
Please help if anyone have any idea on how to resolve this.
From the URL, it looks like your app uses an active directory login. This means that your Cypress test must first log in with a test user. You can achieve this as follows:
In Cypress you can add your own custom commands like described here:
https://docs.cypress.io/api/cypress-api/custom-commands
This way you can write a custom command that technically logs a test user into active directory, e.g.:
Cypress.Commands.add('login', () => {
return cy
.request({
method: 'POST',
url: `https://login.microsoftonline.com/${tenantId}/oauth2/token`,
form: true,
body: {
grant_type: 'password',
tenant: 'tenantId',
client_id: 'clientId',
client_secret: 'clientSecret',
username: 'username',
password: 'password',
resource: 'clientId',
},
})
.then((response) => {
sessionStorage.setItem('access_token', response.body.access_token);
});
});
Then you can use your custom command in your test as first action like:
cy.login();
and then perform your site visit:
cy.visit()
Related
Our app requires Azure b2c authentication when login in. I automated the login by simply typing the username and password. In addition I had to add "chromeWebSecurity": false to avoid cross-origin issue.
I think this is the incorrect way of login in. While I was searching for a solution I came across some articles regarding this. Apparently we could user Cy.request() and get the response and then access the app.
However, I was unable to implement this.
Has anyone implemented the Azure b2c login automation with cypress ? if so can someone explain how this needs to be done ?
Our app uses access bearer tokens.
It first sends authentication requests
GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/authorize
Then gets the token
POST https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/token
Thanks
I'm not too familiar with Azure b2c authentication, but looks like the general pattern is given here How to use Cypress to test your SharePoint solution with an Azure AD-secured API
The bulk of the code is this
Cypress.Commands.add("visitWithAdal", (pageUrl) => {
const config = {
username: process.env.CI ? Cypress.env('USERNAME') : Cypress.env('username'),
password: process.env.CI ? Cypress.env('PASSWORD') : Cypress.env('password'),
tenant: process.env.CI ? Cypress.env('TENANT') : Cypress.env('tenant'),
clientId: process.env.CI ? Cypress.env('CLIENTID') : Cypress.env('clientid'),
clientSecret: process.env.CI ? Cypress.env('CLIENTSECRET') : Cypress.env('clientsecret'),
resource: process.env.CI ? Cypress.env('RESOURCE') : Cypress.env('resource')
};
// Fetch the access token for the Microsoft Graph
cy.request({
method: 'POST',
url: `https://login.microsoft.com/${config.tenant}/oauth2/token`,
header: {
'cache-control': 'no-cache',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: true,
body: {
grant_type: 'password',
client_id: config.clientId,
client_secret: config.clientSecret,
resource: config.resource,
password: config.password,
username: config.username
}
}).then(response => {
if (response && response.status === 200 && response.body) {
const accessToken = response.body["access_token"];
const expires = response.body["expires_on"];
// Store the retrieved access token in the session storage
cy.window().then((crntWindow) => {
crntWindow.sessionStorage.setItem(`adal.token.keys`, `${config.resource}|`);
crntWindow.sessionStorage.setItem(`adal.expiration.key${config.resource}`, expires);
crntWindow.sessionStorage.setItem(`adal.access.token.key${config.resource}`, accessToken);
cy.visit(pageUrl);
});
}
});
});
I started using OAuth2 server with oidc in node js. Github link
My goal is simple, to access https://myserver/me which is UserInfo endpoint.
While trying to learn how to use the server I also used this guide enter link description here
Where I found that I could create token by sending request to endpoint /token.
Into the configuration I added this code(full server code is below):
{
client_id: 'test_oauth_app',
client_secret: 'super_secret',
grant_types: ['client_credentials'],
redirect_uris: [],
response_types: [],
}
In postman I was able to get my the access_token by this request
POST /token
Headers:
Content-Type: application/x-www-form-urlencoded
Authorization: Basic dGVzdF9vYXV0aF9hcHA6c3VwZXJfc2VjcmV0
Body:
grant_type=client_credentials&scopes=api1
I get this as a response:
{
"access_token": "zdjmZo7_BQSIl4iK9IMcBbKffxGO-wQ3jLzzQXTlyws",
"expires_in": 600,
"token_type": "Bearer"
}
When I checked the token by /token/introspection I found out that the token equals to jti.
So I think it actually returns token_id and by that I cannot access /me endpoint.
Here is the whole sample of server that I use:
const { Provider } = require('oidc-provider');
const configuration = {
features: {
introspection: { enabled: true },
clientCredentials: { enabled: true },
userinfo: { enabled: true },
jwtUserinfo: { enabled: true },
},
formats: {
AccessToken: 'jwt',
},
clients: [{
client_id: 'test_oauth_app',
client_secret: 'super_secret',
grant_types: ['client_credentials'],
redirect_uris: [],
response_types: []
}],
scopes: ['api1']
};
const oidc = new Provider('http://localhost:3000', configuration);
oidc.proxy = true
// express/nodejs style application callback (req, res, next) for use with express apps, see /examples/express.js
oidc.callback
// koa application for use with koa apps, see /examples/koa.js
oidc.app
// or just expose a server standalone, see /examples/standalone.js
const server = oidc.listen(3000, () => {
console.log('oidc-provider listening on port 3000, check https://localhost:3000/.well-known/openid-configuration');
});
The proxy is set to true because I have https set up on apache redirecting to this server.
I tried to change response_types, but than it required redirect_uri which I do not want to have in my scenario.
Here is the request I am trying to post it like so:
POST /me
Headers:
Content-Type: application/json
Authorization: Bearer zdjmZo7_BQSIl4iK9IMcBbKffxGO-wQ3jLzzQXTlyws
The response:
{
"error": "invalid_token",
"error_description": "invalid token provided"
}
Did anyone have a similar problem? I found almost the same problem here
but with no solution, unfortunately.
In case someone encounters the same problem. I was able to solve it.
I did not have enough information and I did not know what client_credentials grant type does.
It actually does not authorize the user, but rather some app. So you have no info about the user, hence you cannot get data about the user through the userinfo endpoint.
So if you want to get info about the user, you probably want to use grant type authorization_code.
I found a page where a lot of things is written pretty clearly, so if you are starting with
OAuth server you might want to give this a try.
https://oauth2.thephpleague.com/authorization-server/auth-code-grant/
I try to automate testing with cypress.
For the app to work the user needs to login.
So i try to automate this step.
I wrote following command which i pass in the username password.
Cypress.Commands.add('login', ( userId, pwd ) => {
const domain = 'XXXX'
const clientId = 'XXXX'
const clientSecret = 'XXXX'
const scope = 'XXXX'
cy.request({
method:'POST',
url:`https://login.microsoftonline.com/${domain}/oauth2/v2.0/token`,
header:
{
'cache-control': 'no-cache',
'Content-Type': 'application/x-www-form-urlencoded'
},
form: true,
body: {
grant_type: 'password',
client_id: clientId,
client_secret: clientSecret,
password: pwd,
scope: scope,
username: userId
}
})
.then((resp)=>{
const token = resp.body['access_token']
console.log(token)
//cy.visit('http://{URL}/auth/#access_token='+token)
})
})
With this i get the error message back. That the Username or password is wrong.
Anyone knows how to fix this? or know a better way to setup Cypress with a SSO from azure AD?
The Azure AD ROPC flow should work, when using it, make sure you are using a work account whose format is xxx#xxx.onmicrosoft.com, and it is not MFA-enabled, details see screenshot below. If you don't have such an account, follow this to create one.
In your case, please double-check the username and password, make sure they are correct.(If they are correct, please make sure there is no escape issue in the actual request.)
I test the flow in the postman, it works fine.
I am using the passportjs library to authenticate users into the application. An access token is usually generated when users authenticate successfully with passportjs. I am attempting to create a branch with the github API with this access token but without much success, both using the octokit wrapper as well as posting with super-agent.
I first attempted to authenticate the octokit by providing it username and password, in this fashion.
let octokit=new Octokit({
auth:{
username:username,
password:password
}
});
I was then able to create a ref/branch without much issue. However, when I did the same but with accesstokens generated by github SSO, like this
passport.use(new GitHubStrategy({
clientID: keys.clientId,
clientSecret: keys.clientSecret,
callbackURL: "/auth/github/callback"
},
async (accessToken, refreshToken, profile, done) => {
let octokit = new Octokit(auth: `token ${accessToken}`);
const branchName = 'refs/heads/vue' + Math.random();
let masterHash = '123x123x1231232';
octokit.git.createRef({
owner: owner,
repo: 'gitDemo',
ref: branchName,
sha: masterHash
}).then((data) => {
console.log('data ', data);
});
}
I receive an HttpError: Not found error. Another method that I tried is to post directly to the end point with superagent, putting the acccess code in the authorization header.
const data={
ref:'refs/heads/FooBranch',
sha:masterHash
};
const res2=await request.post('https://api.github.com/repos/SomeOwner/SomeRepo/git/refs')
.set('Authorization','token '+accessToken)
.send(data);
However, I still receive an HttpError :not found issue. I am quite confused as to what I may have done wrong. Thank you and any help would be greatly appreciated!
I found the anwser here
Basically you don't send data using JSON but rather FormData.
So the post should look like this (copied from link):
let data = new FormData()
data.append('client_id', options.client_id)
data.append('client_secret', options.client_secret)
data.append('code', code)
fetch(`https://github.com/login/oauth/access_token`, {
method: 'POST',
body: data
})
In case anyone else comes across this in the future, you have to specify the Content-Type and Accept when making the request. Without specifying it in the headers you will have to send and receive FormData.
Kudos #Github for not mentioning this at all in their docs.
Using node's built in fetch:
const githubRes = await fetch(githubUrl, {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
code,
client_id: config.github.clientId,
client_secret: config.github.clientSecret,
redirect_uri: config.github.redirectUri,
}),
});
const githubJson = await githubRes.json();
const token = githubJson.access_token;
I am putting together an api integration with Dynamics CRM on premise (v8.1/8.2), on a IFD, using the password grant type.
I am retrieving an access token successfully, however when I then try to call endpoints (e.g /api/data/v8.2/contacts?$select=fullname,contactid ) I get 401 - access denied errors. When I log into the CRM with the user I can successfully view this data and the error occurs on all tested endpoints.
Interestingly this morning I realised the tokens retrieved cannot be base64 decoded - is that correct?
I could use some ideas on what to look at next to resolve the problem. Steps I've taken:
Triple checking the initial token request
Triple checked the Service Root URL
Tried on two CRM/Azure setups
Tried with my own (node) code and internet examples
A wide variety of token setups
Confirmed the user exists in Azure and the CRM
Confirmed user has sufficient permissions
Confirmed the application on Azure has all dynamics permissions granted
Confirmed I am on the same network as Azure and the CRM
It seems apparent that I have a configuration issue somewhere in Azure or the CRM. However no guide or question I can find suggests looking at problems I haven't already checked for and I could really use some input from those who have had to make adjustments in obscure settings ect.
Heres my token request:
var options = {
method: 'POST',
url: 'https://login.microsoftonline.com/<snip>/oauth2/token', //for 'intercity technology' (guid is unique)
headers:
{
'cache-control': 'no-cache',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' },
formData:
{
grant_type: 'password',
client_id: ‘<snip>’, //aplication id
client_secret: ‘<snip>’, //any key in the keys list
username: ‘<snip>’,
password: ‘<snip>’, // and their password
resource: ‘<snip>’ //application id
}
};
logger.debug(util.inspect(options));
request(options, function (error, response, body) {
...
Heres my current api request test:
var options = {
method: 'GET',
url: organisation_url + '/api/data/v8.2/contacts?$select=fullname,contactid',
headers: {
Authorization: 'Bearer '+token,
Accept: 'application/json',
'OData-MaxVersion':4.0,
'OData-Version': 4.0,
'Content-Type': 'application/json; charset=utf-8',
'Prefer': 'odata.maxpagesize=500',
'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue'
}
};
logger.debug(util.inspect(options));
request(options, function (error, response, body) {
...
You'll need to use a grant type of 'client_credentials' instead of 'password' as the later isn't supported.
Something like:
grant_type: 'client_credentials',
client_id: ‘<snip>’, //aplication id
client_secret: ‘<snip>’, //any key in the keys list
resource: ‘<snip>’ //CRM Url
Follow the guide here and all the links to ensure the AAD application is registered correctly and the CRM application user is in place.