Authenticating Jenkins through JSON API using password - authentication

I am trying to build a frontend that for certain functionality needs to communicate with a Jenkins backend. In my frontend I want the user to be able to log in with the Jenkins credentials (username and password, using Kerberos) and have these passed to my Jenkins server, upon which I'd like to retrieve the token that can be used to make further API calls to the Jenkins server without disclosing the password in each request.
I know that to be able to make Jenkins API calls I need to use HTTP Basic auth, and it will accept both user:token and user:password. I want to avoid sending the password in each request though.
I also know that I can find my token by going to the Jenkins webpage, log in with my password, go to my profile page and find the token there. I can then base64 encode that into a functioning HTTP basic authentication header. This works fine.
However, I can't seem to find a decent way to programmatically authenticate using the password, trading the password for the token. The best I've been able to accomplish is to do a GET to said profile page at https://<JENKINS_HOST>/me/configure using the user:password basic auth header and then parse the resulting HTML for the api token, which obviously doesn't feel very robust:
$ curl -v --silent https://<USER:PASS#JENKINS_HOST>/me/configure 2>1
| sed -n 's/.*apiToken" value="\([^"]*\).*/\1/p'
<TOKEN>
What I expected/hoped to find was an API endpoint for authentication which would accept user/password and return the token in JSON format. For most Jenkins pages, the JSON API equivalent is found by simply appending /api/json to the URL, however /me/configure/api/json just throws a 404 at me. Does anyone know if there's such a way? All the docs I've found so far just tells you to go to the /me/configure webpage and look it up manually, which doesn't really make sense for a client wanting to pass along authentication.

Jenkins user API tokens are not exposed via the API.
I would just take the API token once manually from Jenkins and hardcode that (rather than hardcoding your password), since the API token never changes unless you explicitly reset it.
Alternatively, you could authenticate with your username and password and store the resulting value from the Set-Cookie header. Sending the cookie value in subsequent API calls would work as expected.

Related

Automate getting access token in Postman using Auth2.0 AuthorizationFlow + PKCE

So I currently have all my requests set up in postman and to be able to make the request to my api I first need to go to the Authorization tab and click "Get Access Token" then a new window appears showing the log in screen from the Identity Server where I can enter the correct username and password to obtain the access token.
I am now wanting to use Postman to test my api however when the access token expires the tests of course fail.
What I want to know is the best way to approach setting up a script that could run the authorization before that request/tests are run.
I can see lots of examples if you only use ClientId and Secret however our Identity Server also requires the user to log in with username and password as that information is needed so that the Identity Info can be included in the returned token as the api called in the request uses this to determine which user to return data for.
Really hitting a brick wall here as I cannot see a way to automate the identity login.
How do others deal with running automated tests against an api protected with IdentityServer login?
You would have to mimic the set of requests and responses that would normally go through the browser. For example, you first make an authorization request. The server responds with a 302 to a login page. You can grab the location header and call the login page. Then you would post the username and password to the login form's action, etc.
You can have a look at this example: https://github.com/curityio/token-handler-node-express/blob/master/test/login.sh this is a set of curl commands which perform such login to an instance of the Curity Identity Server.
You should be able to script it as a series of requests in Postman.

How to access GitHub via Personal Access Token in URL

I maintain a private repository but want to make one file publicly available.
GitHub documentation states that the CURL command below can retrieve a file:
curl -u username:token https://api.github.com/user
But I would like to provide access through a URL. E.g.
https://username:token#raw.githubusercontent.com/me/repo/master/README.md
This always return a 404. Am I missing something?
From "How can I download a single raw file from a private github repo using the command line?", you wouldneed to use a PAT (Personnal Access Token) without the username:
curl -s https://$TOKEN#raw.githubusercontent.com/....
But I would not recommend making that token visible in any way: it would give access to that file and the rest of the repository.
Putting that file in a separate location (be it a separate public repository, or any other online text storage service) would be safer.
For those of you wondering the "why" on 404 vs 401, it's basically a security measure on GitHub's part to output 404 instead of 401: https://docs.github.com/en/github-ae#latest/rest/overview/other-authentication-methods#basic-authentication
For those wondering why we get a 404 in the browser while cURL gives us a success response, you might've assumed that providing the username and password in the URL like https://username:password#somesite.com would pass the credentials along in the initial request. That is not the case - the browser steps in and sees if the page you are requesting returns a WWW-Authenticate response header, and only then does it send your credentials. In the case of your GitHub url, the resource doesn't send back a WWW-Authenticate. If it did return WWW-Authenticate, then you obviously wouldn't run into this problem.
And then there's cURL. cURL assumes Basic Authentication by default and automatically sets the Authorization header to your username and password (either from the url like my previous example, or set through CLI options like in your example), and it sends it regardless of whether or not the server returns a WWW-Authenticate response header.
Unfortunately for us, there's no way to force the browser to send it with the initial request. As to why GitHub doesn't send a WWW-Authenticate response header, it's probably because they don't want to promote the least secure way of authentication - they no longer allow account passwords to be sent this way, after all. However, they do realize its ease of use and have mitigated some of its weaker points by allowing users to use oAuth access token, GitHub App installation access token, or Personal Access Token in its place that can limit its scope of access. So really, it's the browser that is following standards, and GitHub allowing a form of Basic Authentication with some alterations, and cURL immediately passing our credentials into the Authorization header. I believe the below is what's happening behind your requests:
cURL sends a request along with Authorization header → GitHub: "Well, I didn't ask, but yeah, your creds check out" → GitHub: Authorized and redirects to resource
Browser sends request and waits for WWW-Authenticate response before handing credentials → GitHub: "Umm, you don't have permission to access this resource but I can't let you know whether it actually exists") → GitHub: Returns 404 (instead of 401 with WWW-Authenticate header) stopping the browser short from receiving the WWW-Authenticate header response and sending out an Authorization header with the credentials on hand.

Jmeter is not passing the Microsoft authentication in my script for testing performance on my test website, showing Access denied

My application has a microsoft authentication on it before logging into it & I have recorded script but when I am running it, it is showing me access denied error everytime.I have set authentication manager but still same error. See image attached.
I have tried HTTP Authentication Manager & provided login username & password.
Most probably your application uses OAuth therefore it is neither something you can really record and replay nor handle with the HTTP Authorization Manager.
Depending on your application setup you will either need:
To perform correlation of the query parameters
Or to pass the relevant Authorization Bearer token via HTTP Header Manager. The process of obtaining the token can be different depending on your application login chain implementation, check out How to Run Performance Tests on OAuth Secured Apps with JMeter article to get a couple of ideas regarding bypassing 3rd-party provider login challenge in JMeter tests.
Check if you can provide the auth credentials as parameter of the requests.
for example www.abc.com?username=abc&password=abc. Replicate the same with Jmeter
Use Fiddler (or you can get away with browser dev tools if you don't mind searching manually) and log in manually via your browser.
Check the request(s) that are submitted to Microsoft for tokens/GUIDs and search for where the browser got those strings from (it'll be in one of the previous requests' responses' bodies or redirect URLs. In Fiddler you can use the find function on responses, browser dev tools you'll have to find it manually).
You can then use a JMeter Regular Expression Extractor post-processor (or any of the other post processors you prefer) to extract that string from the earlier request into a variable.
In your login request you can then use the value of that variable (if you used regular expression post-processor with a capture group the first group's value will be ${variable_g1}
You'll probably have an anti-forgery value that you can extract from the HTML of the login page which needs to be submitted with the username and password and then in the response you'll get a cookie set and potentially JWT token in the response body/URL.

Format a HTTPS call to Google Cloud using simple API key

I am trying to connect to Google Cloud from an embedded device so I have no access to OAuth authentication. The documents show that I can use simple API key for connecting. I have created a simple API key but I am having problems using it.
I can test the API functions successfully on https://developers.google.com/apis-explorer/?hl=en_US#p/pubsub/v1/ but on this developer's site I don't enter my API key (maybe one is generated automatically in the background).
When I try the same command using curl I get a 401 error:
"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED"
But I am copying the GET or POST command directly from the online API tester and adding my key at the end:
curl -X POST -d '{"policy":{"bindings":[{"role":"roles/editor","members":["serviceAccount:charge...."]}]}}' https://pubsub.googleapis.com/v1/projects/pl..../subscriptions/arriveHomeSub:setIamPolicy?key=AIz....
What am I missing?
With the limited information you have provided, it is tough to identify the root cause but these are some of the possible ones:
You have not used quotes for the URL argument to curl. This could lead to some characters which are part of the URL to be interpreted by your shell in a different manner. Characters like & are usual culprits although they don't seem to be part of the URL you pasted.
curl -X POST -d '{"policy":{"bindings":[{"role":"roles/editor","members":["serviceAccount:charge...."]}]}}' 'https://pubsub.googleapis.com/v1/projects/pl..../subscriptions/arriveHomeSub:setIamPolicy?key=AIz'
You have not described how you're generating your API key and hence I feel that could be one of the possible issues.
You can go over the steps for using Google OAuth 2.0 from Google, it covers a lot about client secrets, access tokens and refresh tokens.
As long as you have your client ID and secret, you can call Google OAuth APIs to generate an access token.
You pass in the current access token as the key argument to your REST API.
Access tokens have very limited lifetime and might need refreshing periodically. If your application needs to periodically refresh access tokens, consider storing the refresh token in your application in a secure manner.

How do I pass credentials to Sonar API calls?

When I try to call:
https://sonar.mydomain.com/api/resources?resource=com.mydomain.project:MY&metrics=ncloc&format=json
I get
{"err_code":401,"err_msg":"Unauthorized"}
How do I pass my credentials?
According to the newest documentation said: SonarQube now support two way authentication:
User Token
This is the recommended way. Token is sent via the login field of HTTP basic authentication, this way will be more safety, without any password. For more information about how to generate a token, please visit this page User Token. Use curl send request like this:
curl -u THIS_IS_MY_TOKEN: https://sonarqube.com/api/user_tokens/search
# note that the colon after the token is required in curl to set an empty password
HTTP Basic Access
Login and password are sent via the standard HTTP Basic fields:
curl -u MY_LOGIN:MY_PASSWORD https://sonarqube.com/api/user_tokens/search
According to the documentation SonarQube uses basic authentication. Try:
curl -u admin:SuPeRsEcReT "https://sonar.mydomain.com/api/resources?resource=com.mydomain.project:MY&metrics=ncloc&format=json"
Obviously the mechanism for passing these credentials is dependent on how you are invoking the API.
This should also work from the web browser. Try logging into the Webui, your browser will normally cache the credentials.
This happens because authentication data does not include in your api call. This is how I solved it.
1.First install a rest client "Postman" to your browser.
2.Open it and put your API call url under "Normal" tab.
3.Go to "Basic Auth" tab and put username,password then click refresh headers.
4.Come back to "Normal" tab. You'll see a header named "Authorization" in header list.
5.Now click "send" button to view results.
6.If you are using 3rd party application, add "Authorization" header to your call with the value generated by postman.