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
Related
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'm trying to write a small bitbucket plugin that enables SAML 2 SSO authentication.
I've been looking at the source code of sample authentication plugins in bitbucket, and it looks quite straightforward.
However, my question is what is the best approach to handle authentication that spans over separate requests.
To do SAML SSO, you have to send a POST to the IdP via the user's browser, and then it sends a SAML token back via POST's again, but then you're no longer in the middle of authentication. So I'm trying to figure out the cleanest way to kickstart the authentication process again, my current thought is as follows:
Have my authentication handler that implements com.atlassian.bitbucket.auth.HttpAuthenticationHandler do a check to see if SAML authentication has happened in the authenticate() method, and then redirect them to the IdP if necessary. (Authentication process has stopped because of the redirect)
Receive the SAML token from the IdP on a separate servlet and check SAML token is good to use. Presuming it's all good, set a servlet request attribute (or session attribute) with the username that has been validated, and then forward the user to the original page they tried to access. This should start the authentication process again.
My authentication handler runs again, checks for the request/session attribute, and this time creates the ApplicationUser that is necessary for authenticate() to complete successfully.
Does this sound like a good approach? I had a look at the bitbucket source code for how the Crowd SSO handler works, but with Crowd SSO it doesn't need to redirect you an external login page, so it doesn't have an example of this flow.
Ideas?
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.
I am currently working on a REST library for .net, and I would like to hear some opinions about an open point I have: REST and authentication.
Here is an example of an RESTful interface used with the library:
[RestRoot("/user")]
public interface IUserInterface
{
[RestPut("/")]
void Add(User user);
[RestGet("/")]
int[] List();
[RestGet("/get/{id}")]
User Get(int id);
[RestDelete("/delete/{id}")]
void Delete(int id);
}
The server code then just implements the interface and the clients can obtain the same interface through a factory. Or if the client is not using the library a standard HTTP request also works.
I know that there are the major ways of either using HTTP Basic Auth or sending a token to requests requiring authenticated users.
The first method (HTTP Basic Auth), has the following issues (partly web browser specific):
The password is transmitted with every request - even with SSL this has some kind of "bad feeling".
Since the password is transmitted with a request header, it would be easy for an local attacker to look at the transmitted headers to gain the password.
The password is available in the browsers memory.
No standard way to expire user "sessions".
Login with a browser interrupts the look and feel of a page.
The issues for the second method are more focused on implementation and library use:
Each request URI which needs authentication must have a parameter for the token, which is just very repetitive.
There is a lot more code to write if each method implementation needs to check if a token is valid.
The interface will become less specific e.g. [RestGet("/get/{id}")] vs. [RestGet("/get/{id}/{token}")].
Where to put the token: at the end of the URI? after the root? somewhere else?
My idea was to pass the token as parameter to the URL like http:/server/user/get/1234?token=token_id.
Another possibility would be to send the parameter as an HTTP header, but this would complicate usage with plain HTTP clients I guess.
The token would get passed back to the client as a custom HTTP header ("X-Session-Id") on each request.
This then could be completely abstracted from the interface, and any implementation needing authentication could just ask which user the token (if given) belongs to.
Do you think this would violate REST too much or do you have any better ideas?
I tend to believe that authentication details belong in the header, not the URI. If you rely on a token being placed on the URI, then every URI in your application will need to be encoded to include the token. It would also negatively impact caching. Resources with a token that is constantly changing will no longer be able to be cached. Resource related information belongs in the URI, not application related data such as credentials.
It seems you must be targeting web browsers as a client? If so you could investigate using HTTP Digest access authentication or issuing clients their own SSL certificates to uniquely identify and authenticate them. Also, I don't think that session cookies are necessarily a bad thing. Especially when having to deal with a browser. As long as you isolate the cookie handling code and make the rest of the application not rely on it you would be fine. The key is only store the user's identity in the session, nothing else. Do not abuse server side session state.
If you are targeting clients other than the browser then there are a number of approaches you can take. I've had luck with using Amazon's S3 Authentication mechanism.
This is all very subjective of course. Purity and following REST to the letter can sometimes be impractical. As long as you minimize and isolate such behavior, the core of your application can still be RESTful. I highly recommend RESTful Web Services as a great source of REST information and approaches.
I agree with workmad3, if session life time needs to be maintained you should create a session resource. Post on that resource with user credentials (either basic authentication or credentials in the body content) will return unique session id. Delete on /session/{id} will log out the user.
If you want to control the session expiry time. When creating new session (post on session resource) the server will set a cookie on the response (using standard set-cookie header).
The cookie will contain expiry time. The cookie string should be encrypted on the server, so only the server can open that cookie.
Every consequent request to the server will send the session cookie in the cookie header. (it will be done automatically for you if your client is a browser). The server needs to "renew" the cookie for every request, i.e. create new cookie with new expiry time (extend session's timeout).
Remember to clear the cookie when the user calls delete on the session resource.
If you want your application to be more secured you can store the client IP in the cookie itself, so when a request arrives the server can validate that it was sent from the "original" client. But remember that this solution can be problematic when proxies are involved, because the server might "see" all the requests as coming from the same client.
The rest authentication I've seen treats the sessions as a REST resource for creation, destruction etc. and then the session ID is passed to and fro. The ones I've seen tend to use the session cookie for this as it's the only way to secure it really. If you pass the session id in the URL, you don't have any way of really authenticating it came from the correct client.
Authentication is a tricky problem with REST though, as it requires some form of state to be kept outside the URL which infringes upon REST principles of the URL being all that is required to represent state.