I've configured a Named Credential to use the JWT authentication protocol (not JWT Token Exchange), but when the component makes a call to my service using the named credential, I don't get the JWT as an Authorization header. I checked all the headers, and don't see an "Authorization" header at all.
When I change the authentication type to basic or JWT Token Exchange, then it works, sending the values I expect.
Should there be a JWT in the Authorization header?
Do I have my issuer and audience set up correctly? When I experimented with JWT token exchange, it seemed picky about those.
Certificate: (empty)
Identity Type: Named Principal
Authentication Protocol: JWT
Issuer: <the host name of my Salesforce instance>.lightning.force.com
Named Principal Subject: <my user name>
Audiences: https://<the base URL of the remote server>
Token Valid for: 10 Seconds
JWT Signing Certificate: My_Sample
Generate Authorization Header: checked
Allow Merge Fields in HTTP Header: checked
Allow Merge Fields in HTTP Body: checked
Outbound Network Connection: blank
My Apex code (actually written by someone else a long time ago), which works for Basic Authentication
HttpRequest request = new HttpRequest();
String statusApi = 'callout:my_named_connection/api/status';
request.setEndpoint(ApiProxy.appendUrlParams(statusApi, request));
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setHeader('Content-Length', String.valueof(body.length()));
request.setBody(body);
request.setTimeout(10000);
HttpResponse response = http.send(request);
Best Answer
You don't get a "JWT" header, because JWT typically (and in the case of Salesforce) uses the "Authorization" header with the Bearer scheme. The Authorization header contains all the JWT information needed. There is no "JWT" in the "Authorization" header itself, because a) it's Base64 encoded and b) does not state "JWT" as such in its three constituents.
Take the HTTP request generated by Salesforce, copy the long string after "Bearer" and get it decrypted and split up into its parts for example here:
https://jwt.io/
Explanations of the elements can be found in the relevant RFCs 7515 and 7519.
Decoding the bearer and finding its elements in the spec helps answering the other questions.
E.g. you will have noticed that Salesforce's "Issuer" becomes "iss" in the (decoded) Bearer token; one RFC uses "joe" as an example for a possible value, but it can be any "StringOrURI". You could provide an URI (which should be "https://...my.salesforce.com", not "... lightning..."), but I'd suggest a Salesforce user name. This is "OPTIONAL"; I don't know your endpoint provider, but if you are not told explicitly otherwise, the success of the communication should not depend on it.
Salesforce's "Audience" is "who or what the token is intended for". (The Bearer token has "aud" and this is only described by RFC 7519.) Although also optional, it is more often decisive. It is also "StringOrURI".
https://<the base URL of the remote server>
looks alright to me.Finally, the decoded Bearer token has
typ: "JWT"
- the closest you can get to what you were looking for.I'd uncheck the two check boxes for "Merge Fields". At least the code you provided doesn't show any use of merge fields.