Jenkins Set User API Token from file instead of generating in UI - jenkins

Is there a way to set the API token of a user manually? In the UI it has a button "Change API Token" which generates the token. Instead I want to set it.
Our old jenkins server crashed and we have to create a new one. Lot of teams are using a remote trigger call similar to below one. Change in the API token impacts all these teams as they have to update their code.
curl -X POST -H "$CRUMB" "http://automation:ef*****************************d#jenkins-url.com/job/log_deployment/buildWithParameters?token=B6472A215********************
The API token in UI is 32 char long. Upon checking the file in jenkins/users//config.xml there is this property jenkins.security.ApiTokenProperty. Seems like it is possible to set this, need some direction please.
<jenkins.security.ApiTokenProperty>
<apiToken>{AQAAABAAAAAwOROgeIy1vAUUOtGIYud+70TXY0pS/pKTe7nLeO8Xtd2BDgXW1RlZ6pL9+bvDrbwHh2xBnebPJAUS3OQt8f/toQ==}</apiToken>
</jenkins.security.ApiTokenProperty>
Thanks!
Update: More info from
https://issues.jenkins-ci.org/browse/JENKINS-32776
User
passwords are stored as salted hashes (SHA-256 or bcrypt); whereas API tokens
are encrypted using an AES-128 ECB-mode block cipher, using a static key shared
among all users.

You cannot set a given token explicitly since Jenkins only stores the hash of a token.
You can, however, copy the hashed value, thus effectively copying a token.
To do this between different masters with different global encryption keys, you need to decrypt the hash of the first master and use that for setting the hash on the second master. It's probably easiest to do that in groovy.

Related

Invalidating Jwt Token without a blacklist

I want to invalidate refresh jwt token without maintaining a blacklist of used refresh tokens with rotations, for this I had the idea of including a ValidationCode in the payload of the RT that the server generates and store whenever 2 refresh tokens are detected being in use with different rotation number (As an example RT2 that the normal user got from his last request and RT3 that the malicious user generated after sending a malicious request using the old RT2).
Once the server finds that a RT2 is in use while the latest one is RT3. The server should "Invalidate" the previous tokens, and issue a new RT when the user reconnects using his password etc. The process of invalidating token is simply changing the ValidationCode in the newly generated token, and accepts any request in which the token is valid + the validation code in the payload matches the one stored in the server for that user.
If Using this approach, if the malicious user try to use RT3 again, even if the jwt token is valid, the ValidationCode now changed and it will not match the one in the server however the newly generated tokens will.
Is this approach secure and good enough to replace blacklisting old tokens? which I think defies the purpose of using jwt at first + wasting time and memory storing the list and querying in the database
What you're describing here is a solution where you can just keep the latest RT used by the user in the database and allow only refresh requests with the RT saved in the DB. This is a valid approach but it has one drawback: you can have only one active pair of AT/RT for the user. If that is OK for you then you can go with this solution.
wasting time and memory storing the list and querying in the database
Either way you will have to query the database, so that doesn't change much. What you gain is a bit of storage space.

Returning client secret in plain text from GET registration request

I was going through the OpenID Connect Dynamic Client Registration specification. Section 4.3 lists the response for a client read request in which the client secret is displayed in plain text.
While obviously the secret needs to be returned in plain text when registering the client, having to return it in plain text on read requests later implies that the secret value itself needs to be stored (likely encrypted) instead of the salted hash of the client secret.
Since client id and secret are basically the same as username/password, I'm wondering why is the spec requiring to return a secret in plain text in this response, basically going against best practices in password storage?
Passwords are a special kind of secret which are often memorized by users. Since users often re-use passwords, it is important not only to hash the passwords (to protect against reversing it), but also to salt it (to prevent rainbow tables from being used). Secrets such as the client_secret are usually generated from a random source and used only once. Someone who gains access from the database can therefore steal the secret, and impersonate the client, but it won't have value elsewhere.
The client secret needs to be available when a client is configured. If you are for example provisioning multiple instances of a service, you might want to dynamically obtain the client configuration including the secret when you are deploying the application.
To recap, there is a different risk model, the secret is assumed to be random and used only once, whereas passwords are often reused. The secret is supposed to contain enough entropy to protect against a brute force attack, passwords are often shorter or from a dictionary.
There is also a use case for making the secret available many times without needing to change already provisioned clients.

OAuth 2.0 State Parameter

I am working with the eBay API using OAuth on my current Meteor project app.
There is a section of the app where I can create an eBay account profile, and assign custom values to the account (such as nick-naming it, etc.). This is where I initiate the OAuth sign-in redirect process.
My question is about the 'state' parameter in the token requests. I understand that it is for helping prevent CSRF, but do I HAVE to use it that way? 'state' does seem to be optional after all.
Let's say I wanted to pass another value into the request call such as the string 'eBay Seller', and expect that the same exact string be returned in the response. I want to use that value to help my app determine which account to assign the returned tokens to (based on which account profile initiated the redirect link).
Is 'state' a valid place to pass in a variable that I expect to be returned exactly as sent? I considered using Session variables to handle this scenario, but quickly realized that this would not work, since the OAuth process takes me outside of my project's domain.
Does OAuth support passing variables that are expected to be returned as sent? Is sending my variable as 'state' allowed or even recommended (or absolutely not recommended?) Is there a better way to achieve what I want to do that does not involve updating database values?
Thank you!
You can send what you want as state. You should try to make sure it's not guessable though, to mitigate against CSRF attacks.
If you want to return useful information like 'ebay seller' then include something for CSRF (e.g. hash of the session key id) and the text 'ebay seller' and delimit them e.g.
2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E73043362938B9824|ebay seller
Now you have the best of both worlds: useful state info + CSRF protection.
Your redirect endpoint logic can check the hash of the session id matches and also confirm the account type from the initial request.

Hashed client secrets for the client credentials OAuth 2 flow in Apache CXF

I'm attempting to implement the Client Credentials flow of OAuth 2.0 to secure a RESTful service, using Apache CXF (version 2.7.12).
My only client (for now) will be trusted to keep the key and secret confidential - I'm aware of the considerations around that.
My question is how I should store the client secret on the authorisation server. In my mind, the 'client secret' is effectively a password, and thus should be salted and hashed. However, CXF's AccessTokenService, which does the comparison between the stored secret and the value passed in on the request, only does a String.equals() comparison, and doesn't seem to give me any hook where I can provide a different mechanism.
This means that I would need to store the client secret in plain text in order to compare it against the plain text value from the request, without a slightly hacky alternative.
Am I missing some obvious functionality that would let me hash the incoming value before the comparison, or am I being overly-cautious with the client secret? Maybe I'm wrong to treat it like a password?
A sort-of answer, for people encountering this question in the future.
My approach was to create a very simple filter (as described here: http://cxf.apache.org/docs/jax-rs-filters.html), which manually creates a SecurityContext (https://cxf.apache.org/javadoc/latest/org/apache/cxf/security/SecurityContext.html), and adds it to the Message as it passes through the Filter.
This means that as the flow continues on to CXF's AccessTokenService, it's identified as already being authenticated.
I also asked a question on the CXF mailing list, and got a very prompt reply from a developer agreeing that he'd recently noticed this as a potential issue, and was looking into it. Within a few hours he'd committed a change which addressed it, and looked like it would have been an ideal solution. Unfortunately, I've still not found time to test it, as my solution works and gives me a bit of extra flexibility that's helpful for other requirements on my project.

Can you recommend a way to generate access token?

My team are coding a web app, which include a server and a client, I think it's obviously not advisable to send user's uid and password to server every request from client.
I am looking for a good choice to deal with this, maybe something like Oauth, is there any efficient approach?
For example, a user with username lyj and password 123456 request login from my client app, the server should check if it is permissible, after login success, the client can send more request to get other resource from server.
My problem is that, except userid and password, is there a way between server and client to make sure who is this guy, is there any suggest to transmit a access token between server and client?
Without much information on your platform and technologies I can only attempt a generic answer. There are several ways in which you can generate a token depending on how you want to use it. MD5 is a well established algorithm and you can use it to generate a oth token using something like username and email etc. Remember that you cannot decrypt MD5 string. So to do any kind of verification you will have to recreate the string using original parameters and then perform a check. If you want a hash that you can reverse you can look at something like base-64.
Both MD6 and base-64 are easily available as libraries in any back end you may be using.
* UPDATE
Looking at your comments that you are working with a stateless client, here is a possible approach to using tokens.
Client performs login for first time. (preferably HTTPS)
Server performs validation and generates a token using MD5(or any other of your choice) using (username+email+ip_address+time_stamp) and sends it back to client
Server creates a new session for this client in the table in the database using userID , ip_address and, time_stamp
Client passes this token back for any future requests.
When client passes the token , server retrieves the session from the database and generates the MD5 hash and compares it with the token client sent. If its the same you are good.
You can also use the time-stamp value a validity window for your tokens so they are not valid forever. Also its impossible to recreate this token unless someone can create the same MD5 hash at the same time down to milliseconds
Modern web application containers have embedded the session tracking functionality. Of course there is always the choice of cookies. Its up to you what to implement...

Resources