The "gold standard" for authentication is OAuth 2.0. It's perfectly documented and rather easy to implement. The basic gist of it is that Salesforce will redirect to a particular endpoint where the user will log in to the service and grant authorization to the client (specified as client_id).
Once authorized, the browser will be redirected back to Salesforce where it will receive a code, and this code is exchanged for a refresh token and a access token. Once set up this way, you can do callouts seamlessly in Apex. Salesforce will automatically detect when an access token is no longer valid and use the refresh token to get a new access token.
Salesforce itself implements OAuth 2.0 in several ways, of particular interest to you, the Web Server Flow. Your app would essentially need to use this exact same protocol, so the connection would be reversed, where you are logging in to your app from Salesforce, rather than logging in from your app to Salesforce. The implementation is standard, so it looks the same everywhere.
Note that there's also something called a Basic login, but that doesn't use a token, but rather the username and password is sent and validated with every request. This is still technically secure, although still discouraged in favor of a better way. I would advise you not use this method if you can help it.
Also, I came up with a workaround for just using a token. In this model, you use the basic authentication model, but you don't have it generate the authorization header automatically, but instead create the header using the merge field syntax in your Apex code, demonstrated with this code:
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint('callout:jotform/user');
req.setHeader('APIKEY', '{!$Credential.Password}');
HttpResponse res = new Http().send(req);
Note that {!$Credential.Password}
is the literal value to use regardless of the API name of the Named Credential. This was a point of confusion previously, so I'm calling it out here.
The pain point here is that you, the developer, will have to get the key on behalf of Salesforce, and copy-paste it into the password field of the Named Credential. The OAuth model is preferred, because it is a standard interface that Salesforce can directly interact with.
A quick Google search shows that there are various open source projects you can use to implement OAuth2 on your server with minimum fuss. Just find one that meets your needs, install, and integrate. This shouldn't take more than a few days to puzzle out for an experienced developer.