Learn › BMC & Server Management › OpenBMC on Real Firmware
Stop sending the password on every request. Open a Redfish session against real OpenBMC firmware, catch the X-Auth-Token out of the response headers, spend it on a privileged read, and prove the BMC enforces it by watching a forged token come back 401.
Look back at Work Order FW-01. Five requests, and every single one of them carried -u root:0penBmc. Five times you handed the full administrator password to the network.
A script that polls a hundred BMCs every minute does that six thousand times an hour. Every one of those is a chance to end up in a log file, a shell history, or a packet capture.
There is a better door, and this firmware serves it.
Basic auth is what you have been using. The user name and password ride along on every request. Simple, and completely stateless: the BMC has no idea the previous request came from you.
Session auth trades the password once for a token. You POST your credentials to the session service, the BMC creates a session, and it hands back a short random string. Every later request carries the token instead of the password.
The token can be revoked, it expires, and it belongs to one session the BMC can see and count. A password can do none of those things.
The service root already told you where the door is: Links.Sessions points at /redfish/v1/SessionService/Sessions. You create a session by POSTing a small JSON body to that collection.
That body is the only place your password appears. Notice what the reply tells you about the account you just used.
prompt: ops@dc-east-fw01:~$ answer: curl -sk -X POST -H 'Content-Type: application/json' -d '{"UserName":"root","Password":"0penBmc"}' "$BMC_URL/redfish/v1/SessionService/Sessions" | jq -r '.Roles[]' output: Administrator hint: POST to /redfish/v1/SessionService/Sessions with -d and a JSON body holding UserName and Password, then pipe into jq -r on .Roles[]
Administrator is a role, and roles are how Redfish does access control. The account you logged in with holds full privileges on this BMC. A monitoring account would come back as ReadOnly and the same token would then be refused a power action.
A POST that creates something returns 201 Created, not 200 OK, and the interesting part is in the headers. Here is the entire response from this firmware.
HTTP/2 201
allow: GET, HEAD, POST
odata-version: 4.0
x-auth-token: yFslQsXeoKMoZCqE0thc
location: /redfish/v1/SessionService/Sessions/YpXoIEAF2i
strict-transport-security: max-age=31536000; includeSubdomains
content-type: application/json
date: Fri, 31 Jul 2026 10:17:26 GMT
content-length: 299
{
"@odata.id": "/redfish/v1/SessionService/Sessions/YpXoIEAF2i",
"@odata.type": "#Session.v1_7_0.Session",
"ClientOriginIPAddress": "10.0.2.2",
"Description": "Manager User Session",
"Id": "YpXoIEAF2i",
"Name": "User Session",
"Roles": [ "Administrator" ],
"UserName": "root"
}
Three lines matter.
x-auth-token is the token itself. It is in a header, not in the JSON body, which is why a plain curl without -D - throws it away.location is the address of the session object that now exists. DELETE that URL and the token dies immediately.ClientOriginIPAddress is the BMC recording who opened the session. It is keeping books on you.The token and the session id above are from one login. Yours will be a different random string every time you POST. What stays the same is the header name, x-auth-token, which is what you write your script against.
Since the token lives in a header, you have to keep the headers. -D - tells curl to dump response headers to standard output, and -o /dev/null throws the body away so only the headers reach your pipe.
prompt: ops@dc-east-fw01:~$ answer: curl -sk -o /dev/null -D - -X POST -H 'Content-Type: application/json' -d '{"UserName":"root","Password":"0penBmc"}' "$BMC_URL/redfish/v1/SessionService/Sessions" | grep -i x-auth-token output: x-auth-token: yFslQsXeoKMoZCqE0thc hint: Add -o /dev/null and -D - to the same POST, then pipe the headers through grep -i x-auth-token
That string is now as powerful as the password until the session ends. Treat it exactly as carefully.
From here you stop sending the password. The token goes in a header named X-Auth-Token, and the request carries no -u at all.
The accounts collection is a good target, because reading it needs real privilege.
answer: curl -sk -H "X-Auth-Token: $TOK" "$BMC_URL/redfish/v1/AccountService/Accounts" ||| curl -sk -H "X-Auth-Token: $TOK" $BMC_URL/redfish/v1/AccountService/Accounts hint: Put the token in a variable first, then pass it with -H "X-Auth-Token: $TOK" to /redfish/v1/AccountService/Accounts. No -u on this request.
Read what comes back on your own machine. You are looking for a normal Redfish collection, served to a request that never mentioned your password.
A token that works proves nothing on its own. Maybe the BMC lets anything through. The test that means something is the negative one: make up a token and watch it get refused.
-o /dev/null throws the body away and -w '%{http_code}' prints just the HTTP status code, which is exactly the fact you want here.
prompt: ops@dc-east-fw01:~$ answer: curl -sk -o /dev/null -w '%{http_code}\n' -H "X-Auth-Token: not-a-real-token" "$BMC_URL/redfish/v1/AccountService/Accounts" ||| curl -sk -o /dev/null -w '%{http_code}\n' -H "X-Auth-Token: not-a-real-token" $BMC_URL/redfish/v1/AccountService/Accounts output: 401 hint: Same accounts URL, but pass a made-up value in the X-Auth-Token header and print only %{http_code}
401 Unauthorized. The same request that worked a moment ago is refused, and the only thing that changed is the token. That is the whole proof: the BMC is checking, not waving traffic through.
Getting a token proves you logged in. It does not decide what you are allowed to do with it. Before you read on, commit to an answer.
>>> Refused. Getting a token only proves you logged in. The session object carries the roles of the account behind it, which is why the reply told you Roles: [ "Administrator" ]. Authentication is who you are. Authorization is what that identity is allowed to do. Redfish enforces both, and the token is where they meet.
One token, reused across a hundred requests, means the password crossed the network once instead of a hundred times. When a contractor leaves, you delete their sessions and every token they hold dies instantly. No password rotation, no scramble.
And because every session is an object with an origin address, the BMC can show you who is connected right now. Try getting that from basic auth.
>>> Three. Each POST creates a resource, which is why the reply is 201 Created and carries a location header pointing at that specific new session. This is how automation leaks sessions: a script that logs in on every loop and never deletes the session will fill the table until the BMC refuses new logins. Log in once, reuse the token, delete it when you are done.
One last thing to prove. When you POST to the sessions collection, the object that comes back really is a Session resource, and it will say so itself.
prompt: ops@dc-east-fw01:~$ answer: curl -sk -X POST -H 'Content-Type: application/json' -d '{"UserName":"root","Password":"0penBmc"}' "$BMC_URL/redfish/v1/SessionService/Sessions" | jq -r '."@odata.type"' output: #Session.v1_7_0.Session hint: The same POST you used to open a session, but ask jq for the "@odata.type" field of the object that comes back
Same trick you used on the service root in FW-01. Every Redfish object will tell you what it is if you ask.
Work Order FW-02, five objectives.
1. Open a session. Save the response body to ~/session.json. 2. Catch the token. Put the token value in ~/token.txt. 3. Spend it. Read the accounts collection with the token into ~/accounts.json. 4. Prove it is enforced. Record what a forged token returns in ~/forged.txt. 5. The challenge. Record the role your session carries in ~/session-role.txt.
The grader takes the token out of ~/token.txt and uses it against the BMC itself. A token that does not work will not pass, so keep the file to the token and nothing else.
Your workstation is booting below with the OpenBMC instance beside it. Open Work Order FW-02, and this time make the password cross the network exactly once.
Practice Session Auth and the Token in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.