How can i implement custom authorization in NATS.io, not through NATS accounts? For example, on a new NATS connection, it contacts a server connected to it, which is marked as an authorization handler. Or implement authorization on another server and somehow associate the token with the nats server?
If I already have a database with accounts and an authorization server, how can I match this with the NATS server?
Related
We're using Keycloak server for authenticating against several IDPS (google, active directory, etc). We have a spring gateway microservice which plays role of a client and several other microservices which play role of resource servers.
When user authenticates via keycloak, we want to associate the authenticated user with some custom fields (like context, roles, user details) from our custom database (NOT Keycloak DB) and send those fields to other microservices as well, so that we do not need to load the fields from DB in every microservice.
How would you do that? Making a GlobalFilter in the Gateway which would add those fields to request headers and setting those headers somehow to the principal object in resource servers? Or using cache (redis) to store the fields on gateway and load them in resource servers? Or do you have some other solution? For example extending access token, overiding UserDetailsService, etc..
What's important to note is, that we don't want to extends Keycloak Database, since we want to have the whole role management in our custom database. Reason for that is that keycloak schema is not very flexible. We want to use keycloak only as a dummy authentication server.
The preferred option for security related values is for Keycloak to reach out to your APIs or custom data sources at the time of token issuance, then include your domain specific claims in JWT access tokens. In keycloak I believe this is done via a protocol mapper, as in this answer.
This design pattern is discussed in the Claims Best Practices article. It is recommended to not send secure values such as roles in custom headers etc, since they are potentially easier to change by a hostile party. Instead each API should receive the JWT and validate it, in a zero trust manner, then use the received claims for authorization.
For non secure values, such as a session_id or correlation_id used for logging, simple HTTP headers work well.
From reading the Microsoft docs on authentication with SignalR, it looks like the only way to authenticate using a bearer token is to send it in the query string on the WebSocket connection.
Upon inspecting the SignalR handshake, it looks like the Authorization header is included in the Negotiate call. Since the connection ID is returned in the negotiate response, the server could keep track of whether that connection ID has authenticated.
Why is it required to add the bearer token to the Websocket connection query string as well?
It seems this is the clue for your question.
When using WebSockets or Server-Sent Events, the browser client sends the access token in the query string. Receiving the access token via query string is generally secure as using the standard Authorization header. Always use HTTPS to ensure a secure end-to-end connection between the client and the server.
Security considerations in ASP.NET Core SignalR
This is the alternative:
SignalR can be used with ASP.NET Core authentication to associate a user with each connection. In a hub, authentication data can be accessed from the HubConnectionContext.User property. Authentication allows the hub to call methods on all connections associated with a user. For more information, see Manage users and groups in SignalR. Multiple connections may be associated with a single user.
Authenticate users connecting to a SignalR hub
Additional:
However, I think you can also try some injection for both server and client. On server eg. use websocket helper and on client eg. use Promise vs XMLHttpRequest.
We are currently analyzing the API gateway for our microservices and Kong is one of the possible candidate. We discovered that Kong support several plugins for authentication but the all based on users stored in Kong database itself. We need to delegate this responsibility to our custom auth HTTP service and don't want to add these users in API gateway database.
It's possible to do this with some code around, instead of using the OpenID connect plugin; in effect you need to implement an Authorization Server which talks to Kong via the Admin (8001) port and authorizes the use of an API with externally given User Ids.
In short, it goes as follows (here for the Authorization Code grant):
Instead of asking Kong directly for tokens, hit the Authorization Server with a request to get a token for a specific API (either hard coded or parameterized, depending on what you need), and include the client ID of the application which needs access in the call (you implement the /authorize end point in fact)
The Authorization Server now needs to authenticate with whatever IdP you need, so that you have the authenticated user inside your Authorization Server
Now get the provision code for your API via the Kong Admin API, and hit the /oauth2/authorize end point of your Kong Gateway (port 8443), including the provision key; note that you may need to look up the client secret for the application client id also via the Admin API to make this work
Include client id, client secret, authenticated user id (from your custom IdP) and optinally scope in the POST to /oauth2/authorize; these values will be added to backend calls to your API using the access token the application can now claim using the authorization code
Kong will give you an Authorization Code back, which you pass back to the application via an 302 redirect (you will need to read the OAuth2 spec for this)
The application uses its client and secret, with the authorization code, to get the access token (and refresh token) from Kong's port 8443, URL /oauth2/token.
It sounds more involved than it is in the end. I did this for wicked.haufe.io, which is based on Kong and node.js, and adds an open source developer portal to Kong. There's a lot of code in the following two projects which show what can be done to integrate with any IdP:
https://github.com/apim-haufe-io/wicked.portal-kong-adapter
https://github.com/Haufe-Lexware/wicked.auth-passport
https://github.com/Haufe-Lexware/wicked.auth-saml
We're currently investigating to see whether we can also add a default authorization server to wicked, but right now you'd have to roll/fork your own.
Maybe this helps, Martin
Check out Kong's OpenID Connect plugin getkong.org/plugins/openid-connect-rp - it connects to external identity and auth systems.
One of a vendor API documentation mentions that their API calls require to use HTTP Basic Authentication scheme, i.e. user:password Base64 encoded but, their token API (Login equivalent) documentation mentions that "..this service implements OAuth 2.0 - Resource Owner Password & Credential Grant"
Isn't HTTP Basic Authentication different from OAuth ?
Yes, HTTP Basic Authentication different from OAuth 2.0. However, the Resource Owner Password Credentials Grant utilizes Basic Authentication Scheme within the Authorization Request for the Client's credentials as described with section 4.3.1. Authorization Request and Response
The Resource Owner Password Credentials Grant is typically used to convert legacy systems to OAuth 2.0 and no more secure than Basic Authentication Scheme.
Resource Owner Password Credentials Grant is intended to be used when no other Grant Types are available and ONLY when there is a high degree of trust between the Resource Owner and the OAuth Client .
Yes, they both are different.
Http Basic : This is for authentication and user credentials are encoded then passed in HTTP header to the client server.
Basic example for HTTP Basic : Just like traditional web application which asked user to provide credentials and these credentials sent to server in HTTP header. Later server utilize those credentials to authenticate the user.
OAuth 2 : This is for authorization, here the client server required authorization of user data(resource owner) from authorization server.
Basic example for OAuth 2 : Let say there is a online game application running on a server, the user accessed the application which starts loading into user's browser. Now that application asking grants from user to post data about games on his Facebook account. Here user authorize his that application to access his Facebook posts through OAuth Standard. Refer the internal mechanism https://www.rfc-editor.org/rfc/rfc6749
Basic access authentication usage is comparable to OAuth 2.0 Client Credentials Grant Type.
A session can be created using Basic Authentication and services can be accessed using a sessionid in a stateful environment.
But if you do not want to use the session due to session limitations or stateless services, you can use the OAuth 2.0 Client Credentials Grant Type instead, which creates a token instead of session and sessionid. This token provides access to the services.
HTTP basic access authentication:
This is the simpler method for meeting the requirements to access a web service. It is simple because it doesn’t require any of the usual processes in a credentials system: cookies, session IDs or access pages. The whole HTTP basic authentication process is based on standard fields in the HTTP header. Thus, it avoids handshaking: the automated process by which two entities establish authenticated communication before starting normal communication via the established channel. This means equipment can communicate with an external device only if there is successful authentication; otherwise, the communication channel is not created. The connection via modem would fail, for example. The secure development of the basic HTTP access authentication method is HTTPs.
To prevent the basic HTTP access authentication method causing the browser to launch a username and password request for each access, the browser must store this information in the cache for a prudent length of time that doesn’t reduce security excessively. These security credentials are usually stored for 15 minutes.
What is this basic HTTP access authentication method like in the real world?
The access credential provided to third-party developers who want to connect to a mobile API is a totally secret alphanumerical ID.
This alphanumerical API key is stored in a secure space on the server.
The developer making requests for a particular service contained in this API should place this secret ID within the HTTP authorization header along with the word Basic. The two elements together allow the server to recognize the alphanumerical credential and provide access.
GET /private/index.php HTTP/1.1
Host: example.com
Authorization: Basic alphanumerical ID
OAuth 2.0:
OAuth represents a step forward in the use of credentials for authentication of API service users. It is a major advance on the basic HTTP access authentication method. Today it is practically the only security method that is almost 100% reliable, and its reliability is based on creating unique authentication tokens for each user. If this access token is compromised, it is deleted and a new one is issued. This means that the API’s own credentials are safeguarded.
The authentication process is as follows:
A user launches a native application and is asked to give a username or email address and a password to identify themselves as a user.
The type of request used to send this credential to the API is a POST request, which ensures private delivery of secret data. This request is sent via the SSL (Secure Sockets Layer) protocol, designed to enable applications to transmit outbound data securely. SSL facilitates giving and receiving encryption keys between applications.
This request allows to validate user credentials and to create ad hoc an authentication or access token that will expire after a time, or if the user or developer responsible for the API believes it to have been breached.
This authentication token is stored in the device to facilitate access to the API’s services that support the application itself.
If we compare both methods, OAuth 2.0 provides better security criteria because any initial request for credentials is made under the SSL protocol and because the guaranteed access object is a temporary token. In the basic HTTP access authentication process, access to API services always relies on sending credentials via the web, specifically in the HTTP header, which makes it much vulnerable to third parties.
I have been trying to wrap my brain around authentication on a REST API.
I've tried to think of a way to successfully authenticate users, keeping in mind that users can access all data on the client, and I've come up with this idea.
Client sends username and password to the server
Server checks if they match a user.
If it does, we create a hashed string with user_id+e-mail+currentTime+salt
and stores this in a database-table with an expiration date.
Server returns hashed string to client
Client sends random request to server including key
Server checks if key is correct and if it's expired
Is this a proper way to do it, and do you see any security flaws?
You're effectively storing session state on the server, which is something you shouldn't be doing on a RESTful API.
Authentication on a RESTful API should simply follow whatever is the standardized authentication method for the underlying protocol. Instead of reinventing HTTP authentication, you should simply require clients to authenticate through HTTP Basic Auth on every request, using the Authorization header. Obviously, all your client-server interactions should be done over SSL.
If you really need some authentication token with an expire date, you can have a resource that provides it once the client is authenticated with basic (like a signed timestamp) but clients should still send that in the Authorization header, with a custom realm, and no state should be stored on the server.