Work with OData secured service - authentication

I want to generate entity classes and Service class of OData secured service.
In OData Java extension page it is written that I need to use org.restlet.ext.odata.Generator class that should get uri and output directory parameters.
But if my OData service is secured the generator instance is not able to generate service classes without username and password of the service.
I did not find any way to pass username and password to generator class.
I get 401 HTTP response code.
Please help.

In the org.restlet.ext.odata.Generator class, in the method main,
The following code would clear the credential details set in the setCredentials() method.
Service service = new Service(dataServiceUri);
if(service.getMetadata() == null)
{
errorMessage = "Cannot retrieve the metadata.";
}
Kindly provide a solution for this issue as I am currently unable to generate the classes for my rest service as the service is secured with an user password.
I tried the following code to generate the code for my secured service uri:
import org.restlet.ext.odata.Generator;
import org.restlet.ext.odata.Service;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
public class ODataRestletGenerator extends Service {
public ODataRestletGenerator(String serviceUri) {
super(serviceUri);
}
public static final String APPLICATION_URI = "http://ldcigkd.xxx.yyy.corp:50033/xxx/opu/sdata/IWCNT/CUSTOMER/";
public static void main(String[] args) {
// Add the client authentication to the call
ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
ChallengeResponse credentials = new ChallengeResponse(scheme, "user", "pwd");
new ODataRestletGenerator(APPLICATION_URI).setauth(credentials);
String[] arguments = { APPLICATION_URI, "/customer/src" };
Generator.main(arguments);
}
private void setauth(ChallengeResponse credentials) {
super.setCredentials(credentials);
}
}

In the org.restlet.ext.odata.Service subclass that is generated by OData extension, you can call setCredentials() and pass an instance of ChallengeResponse including scheme (BASIC?), login (identifier) and password (secret).

Related

I am receiving status 401 Unauthorized when I attempt to call my secured API by keycloak

I have an web application providing an REST API endpoints, secured with spring security and SSO Keycloak.
My web application works fine with protection on and I can access REST API endpoints using web browser, after authentication on keycloak and redirect back to endpoint. I am getting expected JSON response, which mean user and role should be configured correctly.
But when i want to call a provided REST API endpoint from another web application or using Postman, i have every time an error 401 error: unauthorized.
In the header of the request I am putting:
"Authorization": "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgO...." token.
I am able to fetch this token from keycloak in consumer web application and also when I am making a request using postman.
My Keycloak configuration in my spring security config:
#KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
/**
* Defines the session authentication strategy.
*/
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/api/v1/**").hasRole("USER")
.antMatchers("/admin/**", "/app/**").hasRole("ADMIN")
.anyRequest().permitAll();
}
}
My keycloak.json file:
{
"realm": "realm-name",
"auth-server-url": "https://auth.server.com/auth/",
"ssl-required": "external",
"resource": "resource-name",
"verify-token-audience": true,
"credentials": {
"secret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
"use-resource-role-mappings": true,
"confidential-port": 0
}
My method in the controller of the api:
#RestController
#RequestMapping("/api/v1")
public class WakeMeUpController {
#RequestMapping(value = "/test", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
public String testMeUp() {
return "I am tested!";
}
}
This is a part of my client configuration in keycloak:
keycloak Client screen
Rest keycloak config is how it is coming by default.
Thx for your help!
Thank you. The problem was into audience configuration in keycloak.
For a client, you need to configure new Mapping under Client -> <client_name> -> Mappers and add another Mapping with mapper type 'Audience' and appropriate 'Included Client audience' (i choose client id i have used to make request)
Also another problem that i have faced after i solve this one, was that user was authenticated but was forbidden the access to endpoint.
Explicitly adding role into client configuration itself and assigning this role to the user solve it and it is working.
From huge help was setting spring logging to DEBUG
logging.level.org.springframework.security=DEBUG
And also XXX-Authentication header in server response that gives better description what the issue is.

Is there a way to specify which IAuthProvider to use for authentication on a particular Service class?

I have two services within the same project:
[Authenticate]
public class OnlyDoesBasicAuth : Service
{
}
[Authenticate]
public class OnlyDoesJwtAuth : Service
{
}
//AppHost
public override void Configure(Container container)
{
Plugins.Add(new AuthFeature(
() => new AuthUserSession(),
new IAuthProvider[]
{
new BasicAuthProvider(AppSettings),
new JwtAuthProvider(AppSettings)
}
)
{
HtmlRedirect = null
});
}
The way this is set up, I can get into both services using Basic Authentication or with a valid Bearer token. I'd prefer to have it so that only one service can do one means of authentication. Is there a way to specify with provider to use on authentication?
I'm at a loss on how to approach this. I was thinking that maybe there was a way via global request filter or something to that effect, but maybe that's not the way to go. I could split the project into two projects, which will definitely work, but it's not the way I want to approach it.
I'm just looking for a way for the OnlyDoesBasicAuth to only use the BasicAuthProvider on authentication and OnlyDoesJwtAuth to only use the JwtAuthProvider within the same project. Any and all suggestions will be greatly appreciated.
Thanks in advance.
Typically once you're authenticated using any of the Auth Providers you're considered as an Authenticated User everywhere in ServiceStack.
You can restrict access so that a Service needs to be Authenticated with by specifying the AuthProvider name in the [Authenticate] attribute, e.g:
[Authenticate(BasicAuthProvider.Name)]
public class OnlyDoesBasicAuth : Service
{
}
[Authenticate(JwtAuthProvider.Name)]
public class OnlyDoesJwtAuth : Service
{
}
Alternatively you can validate within your Service that they need to be authenticated with a specific Auth Provider, e.g:
if (SessionAs<AuthUserSession>().AuthProvider != JwtAuthProvider.Name)
throw HttpError.Forbidden("JWT Required");

Limit connection in RESTful web service

Is there a way to configure a rest web service to allow only one connection at a time?
I am using Wildfly 9.0.1-Final with the resteasy 3.0.11.Final implementation.
You can use synchronized block on static field:
private static final Object LOCK = new Object();
#GET
#Path("find")
#Produces(MediaType.APPLICATION_JSON)
public Response find(){
synchronized(LOCK){
//your code
}
}

WebAPI 2 Create Custom Authentication Token

I want to create Custom Bearer Token, with some additional information to be store in the token.
Just want to Use Create Token functionality.(something like FormsAuthentication) without using default implementation(ASP.NET Identity) of User Tables.
1) Custom Login method(MyLogin), that will create custom bearer token with additional information(IP Address embedded into token).
2) on subsequent request be able to inspect the additional information and reject(treat the request as unauthenticated) if the additional information does not match some rule.
In case i receive the bearer token and find the request is coming from different IP address then the one embedded inside it, clear/Invalidate the Bearer Token and treat the current request as UnAuthenticated.
I'm by no means an expert but this is the information i gathered.
This seems to be relatively simple to do with ASP.NET Identity.
You need to create your own implementation of a token provider which implements the IAuthenticationTokenProvider interface. You implement the create method so it creates the token just the way you want and then you supply your provider when configuring the authentication middleware.
The configuration in your starup class would look something like this:
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
//Rest of code is here;
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/yourtokenendpoint"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
AccessTokenProvider = new YourCustomTokenProvider() // YourCustomTokenProvider implements IAuthenticationTokenProvider
};
OAuthBearerAuthenticationOptions bearerOptions = new OAuthBearerAuthenticationOptions()
{
AccessTokenProvider = new YourCustomTokenProvider() // YourCustomTokenProvider implements IAuthenticationTokenProvider
}
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(bearerOptions);
}
}
I have never done this myself but I hope this was of some use.
EDIT: To validate the the token you could create a custom action filter that you decorate your controller actions with. In this action filter you could validate the token and do whatever you like with the request. See this guide.

How should I consume a WCF service using MVC3

I am writing a fairly simple MVC3 application that allows a user to retrieve and modify some configuration data held by a WCF service. The configuration data will not change very often but needs to be maintainable by the user.
Once the user is happy with the configuration, they will launch some processing from the UI or by the scheduled execution of a VB script.
I'm fairly new to WCF and even newer to MVC3 but I'd like to make all the comms to and from the service RESTful. Is this a good thing to do?
I'd been planning to perform the service communications from the MVC controller. This would make a HTTP Get request to retrieve the current configuration and a HTTP Post to apply the modified configuration. I'd also use a Get request to launch the processing.
Could anyone provide an example (or point me in the direction) of how I should be doing this?
Please follow the below links for some sample code to build a RESTful WCF Service and the how the client would access the service.
Link to create a RESTful service: here
Link to create a .NET client that consumes the RESTful service : here
Hope the information helps you out.
If you are the owner of web service, you can directly reference implementation of service in your mvc project and use it without web reference. You can write some like this:
// example of ws
public class Service1 : IService1
{
public string GetData( int value )
{
return string.Format( "You entered: {0}", value );
}
public CompositeType GetDataUsingDataContract( CompositeType composite )
{
if( composite == null )
{
throw new ArgumentNullException( "composite" );
}
if( composite.BoolValue )
{
composite.StringValue += "Suffix";
}
return composite;
}
}
// example of mvc action
public class HomeController : Controller
{
public ActionResult Index()
{
IService1 service = new Service1();
service.GetDataUsingDataContract(....)
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
}
The simplest answer I've found was here:, using the channel factory.
I still don't know if it's the best way but it left my code looking clean enough. Below is a sample from my controller.
public ActionResult Index()
{
SettingsModel config = null;
// Set up a channel factory to use the webHTTPBinding
using (WebChannelFactory<IChangeService> serviceChannel =
new WebChannelFactory<IChangeService>(new Uri(baseServiceUrl )))
{
IChangeService channel = serviceChannel.CreateChannel();
config = channel.GetSysConfig();
}
ViewBag.Message = "Service Configuration";
return View(config);
}