How does jetty.security.ConfigurableSpnegoLogin work? - jetty

I'm trying to make a jetty server use kerberos. For this, I found that there is a built-in solution, called org.eclipse.jetty.security.ConfigurableSpnegoLoginService.
Unfortunately, I haven't found any useful documentation for this. There is one closed issue in the github jetty project about this, but those comments did not help either.
Can someone point me to an example on how to use it? I only need this for authentication, but no authorization.
The way I'd use it is something like this:
ConfigurableSpnegoLoginService spnegoLoginService = new ConfigurableSpnegoLoginService(....);
//set up the spnegoLoginService
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
securityHandler.setLoginService(spnegoLoginService);

The SPNEGOAuthenticationTest has a server side component example.
server = new Server();
server.setSessionIdManager(new DefaultSessionIdManager(server));
HashLoginService authorizationService = new HashLoginService(realm,
realmPropsPath.toString());
ConfigurableSpnegoLoginService loginService =
new ConfigurableSpnegoLoginService(realm,
AuthorizationService.from(authorizationService, ""));
loginService.addBean(authorizationService);
loginService.setKeyTabPath(serviceKeyTabPath);
loginService.setServiceName(serviceName);
loginService.setHostName(serviceHost);
server.addBean(loginService);
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
Constraint constraint = new Constraint();
constraint.setAuthenticate(true);
constraint.setRoles(new String[]{"**"}); //allow any authenticated user
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec("/secure");
mapping.setConstraint(constraint);
securityHandler.addConstraintMapping(mapping);
authenticator = new ConfigurableSpnegoAuthenticator();
securityHandler.setAuthenticator(authenticator);
securityHandler.setLoginService(loginService);
securityHandler.setHandler(handler);
SessionHandler sessionHandler = new SessionHandler();
sessionHandler.setHandler(securityHandler);
To use ConfigurableSpnegoLoginService you require (must have / not optional) ...
A Servlet / HTTP Authentication realm
A Servlet Authentication role
A Servlet Constraint + Constraint Mapping
An AuthorizationService (but you don't want a authorization??)
A ConfigurableSpnegoAuthenticator
Not entirely sure how you will satisfy the "no authorization" part with spnego/kerberos + http authentication + servlet constraint / authentication in the mix. Maybe you have to drop the "no authorization" part and define proper authorization / roles, but put everyone in the same role??

Related

Resolve ISitecoreService using SimpleInjector

ISitecoreService accepts database name as a string parameter in its constructor (web or master)
ISitecoreService service = new SitecoreService("master"); //or
ISitecoreService service = new SitecoreService("web");
Is it possible I dynamically send database name as parameter to IoC and resolve it? for example I send web/master string parameter and get a new instance of ISitecoreService
Like this?
container.Register<ISitecoreService>(() => new SitecoreService("master"));
Expanding on Stevens answer as I have experience with Sitecore and I love Simpleinjector.
If you like you can get at the Sitecore configuration when your application is bootstrapping using the configuration factory, access the website site configuration and use the database property.
var sites = Sitecore.Configuration.Factory.GetSiteInfoList();
var website = sites.Single(s => s.Name == "website");
ISitecoreService service = new SitecoreService(website.Database);
container.Register<ISitecoreService>(() => service);
This way your SitecoreService will be newed up with the same database that is defined in the website configuration.

How to add a cookie value to unboundId scim 2 client sdk?

Can't find a way to set a custom cookie value when invoking UnboundId's SCIM 2 client sdk.
I would like to change the example provided here to something like:
Client client = ClientBuilder.newClient().setCookie(<key>, <value>);
WebTarget target = client.target("https://example.com/scim/v2");
ScimService scimService = new ScimService(target);
...
Any idea how to achieve this?
* Don't care if the cookie is set elsewhere as long as it is being set somewhere.
Found it:
Client client = ClientBuilder.newClient();
WebTarget target = client.target("https://example.com/scim/v2");
ScimService scimService = new ScimService(target);
RetrieveRequestBuilder.Typed retrieveRequestBuilder = scimService.retrieveRequest("Users", uuid);
retrieveRequestBuilder.header("Cookie", cookie);
UserResource userResource = retrieveRequestBuilder.invoke(UserResource.class);

ASP.NET Identity / OData using CORS and cookie authentication missing Auth cookie

I have an ASP.NET Identity site and a ASP.NET OData site.
Both sites have CORS enabled and both site are using ASP.NET Identity CookieAuthentication.
When I execute both sites locally on my computer using IIS (not express) the AUTH cookie is being passed in the header on each request to the OData site.
But when I deploy the sites to the production IIS server then the header is missing the AUTH cookie when calling the production OData site.
Both production and my local IIS have the same domain name and CORS is setup to allow all.
The WebApiConfig has
cors = new Http.Cors.EnableCorsAttribute("*", "*", "*");
config.Enable(cors);
Before anyone asks, yes the machine key is the same between sites.
UPDATE
This seems to be a CORS issue.
When both sites are on my local machine they use the same host name and domain name but when the site are on the production server they have different host names and the same domain name.
You might need to specify the "Access-Control-Allow-Origin" inside your OAuthAuthorizationServerProvider.
I'm using OWIN but you should be able to do something similarly.
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
try adding the policy in your OWIN startup class as below. Just keep in mind that the Startup class might have some different class files since it's a partial class. Also, check ConfigureAuth method to see if everything is set according to your needs there. For instance, you set the external signin cookie of Identity as copied below in ConfigureAuth method to allow External Signin Cookeies like facebook and google.
public void Configuration(IAppBuilder app)
{
//
app.UseCors(CorsOptions.AllowAll);
ConfigureAuth(app);
}
app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie);
I finally got this to work.
In the ASP.NET Identity site I have the following:
// configure OAuth for login
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
Provider = new CookieAuthenticationProvider(),
LoginPath = new PathString("/Account/Login.aspx"),
CookieName = ".TESTAUTH",
CookieDomain = ".test.com",
CookieSecure = CookieSecureOption.Always
});
It seems that the important part on the ASP.NET Identity site is that the "CookieName, CookieDomain, and the Machine Key" must match the one on the OData site.
And then on the OData site I have the following:
// configure OAuth for login
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
Provider = new CookieAuthenticationProvider { OnApplyRedirect = ApplyRedirect },
LoginPath = new PathString("/Account/Login.aspx"),
CookieName = ".TESTAUTH",
CookieDomain = ".test.com",
CookieSecure = CookieSecureOption.Always
});
// build the configuration for web api
HttpConfiguration config = new HttpConfiguration();
// Enable CORS (Cross-Origin Resource Sharing) for JavaScript / AJAX calls
// NOTE: USING ALL "*" IS NOT RECOMMENDED
var cors = new Http.Cors.EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
// call the web api startup
WebApiConfig.Register(config);
app.UseWebApi(config);
private void ApplyRedirect(CookieApplyRedirectContext context)
{
Uri absoluteUri = null;
if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, absoluteUri))
{
var path = PathString.FromUriComponent(absoluteUri);
if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath)
{
QueryString returnURI = new QueryString(context.Options.ReturnUrlParameter, context.Request.Uri.AbsoluteUri);
context.RedirectUri = "https://www.test.com/Account/Login.aspx" + returnURI.ToString;
}
}
context.Response.Redirect(context.RedirectUri);
}
The "LoginPath" is required even though it does not exist on the OData site and you can't use a full url to another site for the login path.
I used "OnApplyRedirect" to redirect to the actual Login page.
I'm not sure what the difference is between "config.EnableCors" and "app.UseCors" but the EnableCors seems to be working for now.

WSO2 Admin services BAMMediatorConfigAdmin

I am trying to add BAM server profile (under ESB server) using Admin Web services. I am not seeing any error thrown while executing as standalone program but profile is not getting added. Please advise if below steps are correct -
Get admin cookie by connecting to "AuthenticationAdmin" URL
Create stubs using wsdl2java from "BAMMediatorConfigAdmin" WSDL
String bamcepServerProfileServiceURL = Constant.SERVICE_URL + "BAMMediatorConfigAdmin";
BAMMediatorConfigAdminStub stub = new BAMMediatorConfigAdminStub(bamcepServerProfileServiceURL);
ServiceClient client = stub._getServiceClient();
Options option = client.getOptions();
option.setManageSession(true);
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.COOKIE_STRING, adminCookie);
BAMMediatorConfigAdminStub.BamServerConfig bamConfig = new BAMMediatorConfigAdminStub.BamServerConfig();
bamConfig.setUsername("admin");
bamConfig.setPassword("admin");
bamConfig.setLoadbalanced(false);
bamConfig.setSecurity(true);
bamConfig.setIp("localhost");
bamConfig.setAuthenticationPort("7611");
BAMMediatorConfigAdminStub.SaveBamServerConfig config = new BAMMediatorConfigAdminStub.SaveBamServerConfig();
config.setBamServerConfig(bamConfig);
stub.saveBamServerConfig(config);
Please check #addResource in[1], which creates the profile and calls ,
stub.saveResourceString(resourceString, bamServerProfileLocation);
through #saveResourceString in[2]
[1]https://svn.wso2.org/repos/wso2/carbon/platform/branches/4.1.0/components/mediators/bam/org.wso2.carbon.mediator.bam.config.ui/4.1.0/src/main/java/org/wso2/carbon/mediator/bam/config/ui/BamServerProfileUtils.java
[2]https://svn.wso2.org/repos/wso2/carbon/platform/branches/4.1.0/components/mediators/bam/org.wso2.carbon.mediator.bam.config.ui/4.1.0/src/main/java/org/wso2/carbon/mediator/bam/config/ui/BamServerProfileConfigAdminClient.java

Unable to set headers in apex web service callouts in salesforce

I'm currently trying to call Amazon Product Retail Web Service in Salesforce.
As I mentioned in
Getting WSDL parse error while generating Apex code from WSDL in Salesforce
I was initially unable to generate apex stub class, but I followed the method suggested by #Ballinger and created apex class. I wrote an apex class to use that stub and to set request parameters. The class i wrote is as follows
public class AmazonProductStubNew
{
public static void getResults()
{
System.Debug(' getResults start ');
AmazonWS.AWSECommerceServicePortUS stub = new AmazonWS.AWSECommerceServicePortUS();
stub.inputHttpHeaders_x = new Map<String,String>();
stub.inputHttpHeaders_x.put('AWSAccessKeyId','MyAmazonAWSAccessKeyId');
stub.inputHttpHeaders_x.put('Timestamp','2012-11-28T12:11:30Z');
stub.inputHttpHeaders_x.put('Signature','Encrypted Secret Code');
String MarketplaceDomain = '';
String AWSAccessKeyId = 'MyAmazonAWSAccessKeyId';
String AssociateTag = '';
String XMLEscaping = '';
String Validate = '';
AmazonWS.ItemSearchRequest Shared = new AmazonWS.ItemSearchRequest();
Shared.SearchIndex = 'DVD';
AmazonWS.ItemSearchRequest[] Request = new AmazonWS.ItemSearchRequest[1];
Request[0] = new AmazonWS.ItemSearchRequest();
Request[0].Title = 'Inception';
AmazonWS.ItemSearchResponse_element response = stub.ItemSearch(MarketplaceDomain,AWSAccessKeyId,AssociateTag,XMLEscaping,Validate,Shared,Request);
AmazonWS.Items_element[] localItems = response.Items;
System.Debug(localItems[0].TotalResults);
}
}
Even though I've added HTTP headers to stub, I'm not getting it in XML Request message
XML Request is as follows
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header />
<env:Body>
<ItemSearch xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
<MarketplaceDomain>
</MarketplaceDomain>
<AWSAccessKeyId>MyAWSAccessKeyId</AWSAccessKeyId>
<AssociateTag></AssociateTag>
<XMLEscaping></XMLEscaping>
<Validate></Validate>
<Shared><SearchIndex>DVD</SearchIndex></Shared>
<Request><Title>Inception</Title>
</Request></ItemSearch>
</env:Body></env:Envelope>
Since headers are not there in SOAP Request, There is a SOAP fault asking for Signature from Amazon Server.
As you can see, I'm new to Salesforce Apex. I followed the steps in
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_web_services_wsdl2apex.htm#http_header_support
to set the headers.
Any idea on why the header isn't getting added?
P.S I added headers manually and tried in SOAP UI, I'm getting proper response.
Thanks :)
I think you're using wrong functions :) (question is indeed confusing).
SOAP (or generally HTTP) communication consists of sending headers and actual message (payload if you like). Headers are short text thingies, message is often a giant XML.
Your code is setting HTTP headers (which are used in web communication to authenticate, provide info about your browser, preferred languages, set cookies, return status codes like 404 page not found...) Please don't be offended with the "for dummies" but I realize the wikipedia article is a bit too much, this might be simpler: http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/
And what I suspect Amazon's webservice wants is just some fields inside the <env:Header>...</env:Header> tag? Just check the generated apex code for existence of subclass called "Header" (you can also search for the variable names like "Signature". This is going to be a total wild guess but I think you'll have to write something like that:
AmazonWS.AWSECommerceServicePortUS stub = new AmazonWS.AWSECommerceServicePortUS();
AmazonWS.Header h = new AmazonWS.Header();
h.AWSAccessKeyId = 'MyAmazonAWSAccessKeyId';
h.Timestamp = '2012-11-28T12:11:30Z';
h.Signature = 'Encrypted Secret Code';
stub.Header = h; // plug it into the request
// create and plug other required tags
AmazonWS.ItemSearchRequest Shared = new AmazonWS.ItemSearchRequest();
Shared.SearchIndex = 'DVD';
AmazonWS.ItemSearchRequest[] Request = new AmazonWS.ItemSearchRequest[1];
Request[0] = new AmazonWS.ItemSearchRequest();
Request[0].Title = 'Inception';
// ...
Now, to make it more confusing you might still have to use a HTTP header, there's a special one called SOAPAction. But generally speaking I believe you're after placing your data in the XML, not in http headers.
Funny enough, I've downloaded the Java example from http://aws.amazon.com/code/Product-Advertising-API/2478 and if I read it correctly they're passing the signature in the URL (endpoint), not in the XML. Probably because it's a REST GET method (if you can access that API it could save you a lot of hair pulled, SOAP is clunky).