Using basic authentication I do this in my authentication handler:
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var authHeader = request.Headers.Authorization;
if (authHeader == null || authHeader.Scheme != BasicScheme)
{
return CreateUnauthorizedResponse();
}
// Now authenticate the user with his name+pw
// Return Auth token to user
}
Every time that means the first request or all subsequent requents the user request will go through the above SendAsnyc method. How should I differentiate in the above method wether the user want to authenticate himself (having username+password) the first time or authenticate himself (having the server generated auth token) all further times?
Two options.
(1) Assuming that the token that is sent back from the server after successful authentication of username/password is sent in the Authorization header for subsequent requests (in a different scheme), rearrange your logic so that you look for basic scheme in authorization header and if present, authenticate and send back the token. If authz header with basic scheme is not present but your scheme or bearer scheme (whatever that is) is present, assume it is token and authenticate. If authz header is not present or if credentials in basic scheme is invalid or the token in the other scheme is invalid, send 401.
(2) Change the message handler so that it only does basic scheme authentication. If header is absent or invalid credentials or present, it just will not set the correct principal in request.GetRequestContext().Principal but does not send back 401. Introduce another message handler that will perform the authentication of token. This handler sets the correct principal only when the token is present in the request and token is valid. Again, this handler does not send back 401. Finally, apply Authorize filter at action method, controller or even globally. Filter will set the response status to 401, if an authenticated identity is not established by both message handlers.
I prefer the second one because the handlers have single responsibility of authentication. BTW, it is generally not recommended to use message handler to do authentication. The identity you establish here will be reverted back, once the execution goes back to IIS pipeline (assuming you use IIS).
You can use the authorization scheme to differentiate. When the user is sending a username/password then use the "basic" auth scheme. When sending a token, use the "bearer" auth scheme.
Related
I'm using .NET 6 with HttpOnly cookie-based JWT authentication in my WebAPI, and I'm now implementing token refresh.
I store the JWT and a Refresh Token in cookies, e.g.:
X-Access-Token: eyJhbGciO...
X-Refresh-Token: d8085ec8-d0bc-4e5c-b6b6-cd76146c419f
Most flows I've found for token refresh look like this, with the client calling the /refresh endpoint to get a new JWT:
client sends request to server
server rejects request with a 401 Unauthorized
client requests new JWT (expired JWT and Refresh Token automatically sent to server in cookie)
server validates cookie Refresh Token, generates new JWT and Refresh Token, assigns to cookies
client sends original request to server, with the new JWT and Refresh Token in the cookie
My question is:
When the initial request with the expired JWT is received by the server, since the server already has the refresh token (sent in the X-Refresh-Token cookie), can't the server issue a new JWT and Refresh Token at that time and successfully complete the request? This completely eliminates the need for a separate request and response to refresh the tokens. This is the flow:
client sends request to server
JWT is expired, but Refresh Token is valid
server creates new JWT and Refresh Token, assigns to cookies
server successfully completes the request
Is there a vulnerability or security risk implementing the refresh this way? I cannot think of one, but I could not find any examples with this flow.
Thanks!
Why are you using JWT access tokens? If the server could respond with an updated access token by looking at the refresh token, then why wouldn't the server just look at refresh tokens every time, and then the JWT access tokens aren't needed?
The point of using JWTs, and access tokens in general, is that it allows stateless authentication with services that have no access to the refresh token store. Usually, you will have an authentication service, it stores the refresh tokens, and calls to /refresh get routed to it, and it will validate the refresh token, and issue the access token. Then, calls to other services are able to validate the access token, without needing to make any calls on the authentication service. So, the reason why they don't just reply with a new access token when authentication fails is because those services are incapable of checking the refresh token, they don't have access to the refresh token store, only the authentication service does.
If however your application is one big monolith, where every endpoint is hosted by the same server and therefore is capable of checking refresh tokens and issuing access tokens, then there is absolutely no reason for you to be using access tokens or JWTs in general. You should just use refresh tokens, which, in this case, would be better called a session token.
We wish to use our own httponly strict cookie with access and refresh token in it for our microservices architectures.
We are primary using OKTA Authentication API to log users with our own custom Sign-in page.
We were able to get the access_token on the authorize endpoint using the responsetype=token with sessionToken and redirecting the result as a form_post on our back-end endpoint.
I was unable to retrieve the refresh_token despite adding the offline_access in the scope even if it is checked in my okta application setting.
I don’t want to use resource password flow since we prefer using sessionToken which will work with multi factor if needed in the future.
I also try using the code flow and redirecting the result on our back-end but since the code flow is client-side it’s return this error "PKCE code verifier is required when the token endpoint authentication method is ‘NONE’." This error occur even if we choose a .NET application
How can we retrieve the refresh_token server-side with Okta?
Responded to your post here https://devforum.okta.com/t/getting-refresh-token-server-side-sessiontoken/12419/3.
Aside from making a call directly to /token with your access token you can also check our Early Access feature called Refresh Token Rotation. Let us know if this helps!
I was able to use the CODE flow and redirect from server-side to the authorized endpoint like so:
https://{YOUROKTADOMAIN}/oauth2/default/v1/authorize?client_id={YOURCLIENTID}&response_type=code&scope=openid%20offline_access&response_mode=query&redirect_uri={YOURSERVERSIDEGETURI}&state={Guid.NewGuid()}&sessionToken={SessionToken From Auth API}
This call will post back to my same server, so i can handle token myself and create my own cookie.
Starting with the following repo at https://github.com/mjrousos/IdentityServer4Authentication, I added a "ValuesController" with a single "Get" method with the [Authorize] attribute. When I login using the web front end I'm able to access this endpoint just fine - the web bits contain the standard web bits found in the IS4 Quickstarts.
However, when I request a token from the token endpoint (/connect/token) with the following body (raw) "grant_type=password&username=gvdonovan%40gmail.com&password=Pass20!7&client_id=myClient&scope=myAPIs" and then use this token in a Get request with a single Authorization header with a value of "bearer [my token]" I receive a 401 Unauthorized response.
You've got your Identity Server and your 'protected controllers' in the same project, with a single startup, which is a configuration I'm not used to.
For our use of IdSvr, we made sure that the startup for the client (a web api) used the middleware "UseIdentityServerAuthentication" in the configure method, with appropriate definitions for what the acceptable Authority and AllowedScopes are for that client.
Then the use of the Authorize header on protected API resources will auto-magically call the authority (our IdSvr) to verify the token.
Our IdSvr doesn't have controllers or "app.UseMvc", because it is just for issuing/verifying tokens.
I have a couple of days following a few issues but I can not find the solution .
I have followed these issues: Custom JAX-RS authorization - using JWT in each request and
Best practice for REST token-based authentication with JAX-RS and Jersey
but I do not understand how to use filters.
I need to create a token for a android app Use the resources of my web service.
I can not just create a token and send it ?
I 'm using jjwt https://github.com/jwtk/jjwt but I think it right, a piece of code:
#POST
#Produces("application/json")
#Consumes("application/x-www-form-urlencoded")
public Response authenticateUser(#FormParam("username") String username,
#FormParam("password") String password) {
try {
// Authenticate the user using the credentials provided
// authenticate(username, password);
// Issue a token for the user
String compactJws = Jwts.builder().setSubject(username).signWith(SignatureAlgorithm.HS512, "pepe").compact();
// Return the token on the response
return Response.ok(compactJws).build();
} catch (Exception e) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
If anyone can help me , thanks ...
Si alguno me puede responder en castellano, mejor.
PD: Sorry if I asked the question wrong, I'm new in stackover... and sorry for my English
I am the author of the answer about token-based authentication in JAX-RS. This authentication method can be summarized in the following steps:
Exchanging hard credentials for a token
No filters are required to do it. You should have an endpoint (a JAX-RS resource method) to perform the authentication using hard credentials (like username and password). If the credentials are valid, the endpoint is going to issue a token that will be sent to the client in the response payload. The client must sent this token in the Authorization header of each request.
The endpoint that issues the tokens must not be protected, that is, no authentication must the required to access it. Once you have an Android application as client, I think you will find better consuming application/json instead of application/x-www-form-urlencoded. My answer provides details on how to do it.
Validating the token
Here the authentication filter comes into play. When using filters to validate the tokens, you can keep your endpoints lean and business focused.
The idea behind the filter is to intercept the requests to protected resources, extract the token from the Authorization header and validate it. If the token is valid, the request will proceed to the requested endpoint. If the token is invalid, the request will be aborted.
Besides the authentication filter, you can have other filters to perform authorization, for example. In the authentication filter, you must check if the token is valid and then find the user you issued the token for. In the authorization filter, you must ensure the user has enough permissions to access the requested resource. Other filters can be created according to your needs.
The code you have provided is valid to a issue a new token for a web application (uses application/x-www-form-urlencoded), but for android application It would probably be more appropriate send credentials as a json POST or in a Authorization header
After this, the client application receives the token, stores it and needs to include the JWT in every request to server. You can include the token in headers or in a request param. The server must validate the token signature, and other fields like sub (the userId) and exp (expiration time).
Using a filter, like the AuthenticationFilter provided in the example, simplifies the authentication process. It can intercept all the requests and perform the validation in a unique point. If not, you would have to validate the JWT in each method of your bussiness logic
If you have doubts about how to configure the filters I suggest to post in SO an specific question
I'm aware of how AEM creates cookie called "login-token" after successful authentication .
My question is how AEM validates this cookie in each request? Is there any filter available to intercept the request and then validate cookie? if not then how AEM invokes sling authentication handler again?
I could not find here http://host:port/system/console/status-slingfilter
Please help me to clarify this
authentication is not done via a filter. authentication is done before filter processing.
as soon as request arrives OSGi HttpService calls handleSecurity of the HttpContext associated with the servlet/resource. In case of Sling this calls into SlingMainServlet.handleSecurity which calls SlingAuthenticator.authentication.
SlingAuthenticator selects an authenticationHandler for the request and forwards the authenticate call.
authentication handler implements extractCredentials method that (based on the auth scheme e.g. Authorization header based authentication, session based authentication or cookie based authentication) is responsible for reading credentials from cookies (or header or session).
It would return AuthenticationInfo after successful authentication, if authentication fails either an anonymous session is acquired (if anonymous is allowed per configuration) or requestCredentials method is called, which would render(or redirect to) a login form.
after handleSecurity execution is done, HttpService would either terminate the request (if handleSecurity returned false) or call SlingMainServlet.service which would be the entry point for Sling Request Processing.
Request level filters would be processed after that. see https://sling.apache.org/documentation/the-sling-engine/filters.html