Here is an excerpt from Picketlink Federation 2.5.4 SP4 class org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler which shipped with Jboss 6.4 (no tag on picketlink.org github for 2.5.4 SP4?). My problem is that the top line, request.getRequestDocument() returns null. The object itself, request (SAML2HandlerRequest) looks fine (not null):
public void handleStatusResponseType(SAML2HandlerRequest request, SAML2HandlerResponse response)
throws ProcessingException {
HTTPContext httpContext = (HTTPContext) request.getContext();
ResponseType responseType = (ResponseType) request.getSAML2Object();
(...)
Document responseDocument = request.getRequestDocument();
Element assertionElement =
DocumentUtil.getChildElement(responseDocument.getDocumentElement(),
new QName(JBossSAMLConstants.ASSERTION.get()));
if (assertionElement != null) {
try {
Document assertionDocument = DocumentUtil.createDocument();
Node clonedAssertion = assertionElement.cloneNode(true);
assertionDocument.adoptNode(clonedAssertion);
assertionDocument.appendChild(clonedAssertion);
String assertionAttributeName = (String) handlerConfig
.getParameter(GeneralConstants.ASSERTION_SESSION_ATTRIBUTE_NAME);
if (assertionAttributeName != null) {
session.setAttribute(assertionAttributeName, assertionDocument);
}
session.setAttribute(GeneralConstants.ASSERTION_SESSION_ATTRIBUTE_NAME, assertionDocument);
} catch (ConfigurationException e) {
throw new ProcessingException("Could not store assertion document into session.", e);
}
}
FYI, the reason I need this document is is that as you see in the code, if the responseDocument is null, then the asserionElement is null. And if the assertionElement is null, then my SAML token will not be in the HTTPSession under the key given, and that is what I need.
The identity provider is PingIdentity. And tips or tricks on what could be going on here before I have to learn the whole PicketLink code base?
Thanks!
FYI my set up is jboss 6.4, with the picketlink it ships with (2.5.4 SP4), with PingIdentity for SAML tokens (IdP). FYI, all is working in an SSO scenario from WebApp 1 to WebApp 2, the only thing is that I need to get the SAML token from the SSO session on WebApp 2....
Got it ))), the PingIdentity IdP SP Connection, Browser SSO, Protocol Settings, I had "Encrypt the Entire Assertion". Setting that to "None", fixes it and I get my token in the HTTP Session. So... ...with PKI, we encrypt with public key (cert) and decrypt with private key (key). So either picketlink did not have the right private key (but I think it did) or the two systems don't understand how to do this PKI encrypt/decypt...
Related
I have Java web application which implemented Apache shiro Authentication & Authorization.
Now i need to implement API Key to the existing project (which has apache shiro).
Please help me on implementation part. Even i could not find any documentation
PS:: We have already implemented 3 different types of Custom Realm(jdbc,ldap,Pac4jRealm) but now struggling to implement the API key concept with Apache Shiro.
I resolved the above issue by extending the JDBCRealm,see the below example code
public class APIRealm extends JdbcRealm {
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = null;
AuthAPIInfo authInfo = null;
try {
String apiKey= (String) principals.getPrimaryPrincipal();
authInfo=fetchAPIKeyInfo(apiName);
// Do all the other stuff like checking for Authorization and setting it to token
} catch (Exception e) {
insertAPILogActivity(authInfo, "User not authorized");
}
return info;
}
private AuthAPIInfo fetchAPIKeyInfo(String apiKeyName) {
//Connect to Database using JDBC connection and validate the API Key and return the AuthAPIInfo
}
}
Add the above realm in shiro.ini
apiRealm=com.example.APIRealm
securityManager.realms=$apiRealm
I have Liferay 7.2.
I created a module rest.
It is possibile to save a variable in session ad use it in other method?
My idea of code is:
#GET
#Path("/save/paramt")
public String jsonSaveParamRequest() throws Exception {
String json = "xx";
//SAVE IN SESSION json
return "ok";
}
#GET
#Path("/get/paramt")
public String jsonGetParamRequest() throws Exception {
String xx= SESSION VARIABLE json
return xx;
}
Saving state in a HTTP session in a REST API is not recommended and should be avoided. Please refer to the discussions here SO:how-to-understand-restful-api-is-stateless.
Technically, I guess this is possible as you can inject the HttpServletRequest as a method param via #Context HttpServletRequest request to your annotated method and use getSession(). But I am not sure if you can rely on that.
Following the documentation here and there, I managed to setup an Authorization Server that gives out JWT access tokens signed with asymmetric key, which are verified locally by a Resource Server using a local copy of the public key. So far so good.
My final goal is for Resource Servers to use the JWKS endpoint on the Authorization Server, and use the 'kid' header in the JWT to lookup the right key in the JWKS and verify locally, supporting key rotation.
I've found how to make the Authorization Server expose a JWKS endpoint, and also how to specify the key-set-uri for the resource server.
However, it seems that there is no way to
publish kid (key id) values in the JWKS
include the kid header in the JWT
Is there a way to do this?
I found a way to set the kid in jwks endpoint:
#FrameworkEndpoint
public class JwkSetEndpoint {
private final KeyPair keyPair;
public JwkSetEndpoint(KeyPair keyPair) {
this.keyPair = keyPair;
}
#GetMapping("/.well-known/jwks.json")
#ResponseBody
public Map<String, Object> getKey() {
RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
RSAKey key = new RSAKey.Builder(publicKey)
.keyID("YOUR_KID_HERE")
.keyUse(KeyUse.SIGNATURE).build();
return new JWKSet(key).toJSONObject();
}
}
What I did not find was a way to set it in the header of JWT.
While having the same problem I stumbled upon this post. So i hope it will be useful to someone. I do not think this is the best solution, so maybe some one comes up with a better answer i hope like setting some external bean for example.
Background:
The Jwk store is comparing the KID in the token header with the one in memory if not available it will request the well-known endpoint
So putting the KID in the JwkSetEndpoint will result in a json file with the kid inside.
next to this you need to get the KID on the header of the jwt token.
my solution in my class which extends JwtAccessTokenConverter
#Override
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String content = null;
try {
content = objectMapper.formatMap(getAccessTokenConverter().convertAccessToken(accessToken, authentication));
} catch (Exception e) {
throw new IllegalStateException("Cannot convert access token to JSON", e);
}
Map<String, String> headers = getJwtHeader();
String token = JwtHelper.encode(content, signer, headers).getEncoded();
return token;
}
next to the KID header the Tokenstore expects a use header set to signing.
i also had to override the signer object because i got stuck with a hmac signer instead of the desired RsaSigner.
we keep fighting with out multi tenant application.
This is an ASP MVC EF6 Code First web application.
We initialize a list of tenants in the Application_Start, getting a pair of values:
Host
TenantId
So we can associate any host with one TenantId, and store that list in cache.
We have configured a custom filter to get the current tenant.
public class TenantActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Items.Add("TenantId", GetCurrentTenant(filterContext.HttpContext.Request.Url.Host));
base.OnActionExecuting(filterContext);
}
}
The GetCurrentTenant function just access the list in cache and get the current one based on the host passed.
Is it correct to store the current tenant in an item in the context?
After that, we have created an Interceptor to get any query and add a filter to filter by TenantId. This is done and working good, we just need to add the tenantId from the context:
The problem we have is where we get the TenantId for each request.
if (HttpContext.Current.CurrentHandler == null) return;
var clientId = Convert.ToInt32(HttpContext.Current.Items["ClientId"]);
foreach (DbParameter param in command.Parameters)
{
if (param.ParameterName != TenantAwareAttribute.TenantIdFilterParameterName)
continue;
param.Value = clientId;
}
We don't know if this is the correct approach since there is a lot of informationon the net.
Thanks.
In my experience, the persistence of the tenant Id in the HTTP context is not right, as in some cases, the HTTP context becomes null.
You can try to get the tenant Id from the claims of the current principal. Creating a static class with a tenant identifier property that reads from the claims and gives is more reliable. Assuming you are using the owin pipeline, this should be easy to do. You can take a look at the reference sample application from github here
It looks like the below block,
public static class UserContext
{
public static string TenantId
{
get
{
return Threading.Thread.CurrentPrincipal.FindFirst("tenantid");
}
}
}
I have REST service requirements in which some calls require authentication and some don't. Absolutely no state is used, as the calls are all independent from one another. I have put something together which seems to work, but is this the right way to go about not using sessions?
This question is kind of related to my WCF question which is answered here.
Firstly I registered the authentication method:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new CustomCredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
}
));
I then attribute the respective calls (or service or DTO) with the Authenticate attribute:
[Authenticate]
public HelloResponse Post(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name + " with POST & Auth"};
}
I inherit from the BasicAuthProvider class which does the authentication:
public class CustomCredentialsAuthProvider : BasicAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
return userName == "dylan" && password == "abc123";
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
session.IsAuthenticated = true;
//Important: You need to save the session!
authService.SaveSession(session, new TimeSpan(0,0,10));
}
}
As you can see, I do save the session but it times out after 10 seconds. This is the part that I'm sure can potentially be done better. It seems to work nicely though.
Is there a better way of doing what I'm trying to accomplish?
Is there also any way, due to the sessionless nature of these services, to remove the Auth, AssignRoles and UnassignRoles methods?
If you wanted to keep using ServiceStack's Authentication and Session support you could just add a response filter that clears the user session after the service is executed, e.g:
this.ResponseFilters.Add((req, res, dto) => req.RemoveSession());
Basically after each request is executed it clears the session, so no record of them having authenticated exists.
Otherwise you can just skip using ServiceStack's Authentication completely and just provide your own via RequestFitlers of FilterAttributes (which is essentially what SS Auth does under the hood).