I've created a REST API in an Area of my ASP.NET MVC 4 web application. The API is working properly, and I'd now like to secure it.
Is there a very simple example of how I can do this? I'm going through the samples that came with the DotNetOpenAuth download and I'm completely lost on it.
I had the same problem a couple of days ago. This answer is ridiculously long, maybe there's an easier way.
Personally, I don't use DNOA anymore because it is designed towards self-validating (i.e. encrypted tokens) so you don't need to hit the DB with every request. A very important side effect of this is that an access revocation will not become effective immediately, but only after the token must be renewed. Also, access tokens will become quite long (around 500 bytes).
As a very first step, make sure you know what you need:
OAuth / OAuth2 look easy at first, but it's important to understand how the authorization workflows are designed. Also, their terminology can be irritating, for instance 'Client' refers to what I would naively call client application. It's not the user (who is called 'resource owner' in OAuth terms). My suggestion: Read RFC 6749. It looks dull, but it's an interesting read (and you can skip half of it...)
A key question is: Do you need 2-legged OAuth or 3-legged OAuth (or both?). Which grant types do you need to support?
If you basically want to replace HTTP Basic Auth, the simple "Resource owner password credentials flow" will do. The facebook/twitter kind type of "have this application access my profile information" is 3-legged OAuth.
There's an IBM Documentation that comes with nice grant type diagrams.
Now to DNOA, take a look at Samples/OAuthAuthorizationServer.
A good entry point is the OAuthController.cs file. Note that the Authorize and AuthorizeResponse actions are required only if you want to enable your users to give access to third party applications (3-legged OAuth).
In a 2-legged scenario, users access the OAuth token endpoint directly and simply request an access token. In any case you will need such a controller in your REST application.
The key to the inner workings is the OAuth2AuthorizationServer class (NOT the AuthorizationServer class). Look at Code/OAuth2AuthorizationServer.cs. It implements IAuthorizationServerHost.
Half of that class deals with data storage (which you might want to modify if you're working with a different datastore), and half of it deals with the encryption of the access tokens. You will need to implement IAuthorizationServerHost for your application, too.
Make sure you have a line #define SAMPLESONLY in your code, so it will accept the hardcoded certificate.
To actually authorize the request, it is helpful to write a custom ActionFilterAttribute. Here's some super condensed code, not production ready:
public sealed class BasicAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
private readonly OAuthResourceServer _authServer;
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization.Scheme == "Bearer"
|| actionContext.Request.Properties.ContainsKey("access_token"))
{
authenticatedUser = _authServer.VerifyOAuth2(request, required_claims);
HttpContext.Current.User = authenticatedUser;
Thread.CurrentPrincipal = authenticatedUser;
}
}
}
// See OAuthResourceServer/Code/OAuthAuthorizationManager.cs in DNOA samples
public sealed class OAuthResourceServer
{
public IPrincipal VerifyOAuth2(HttpRequestMessage httpDetails, params string[] requiredScopes)
{
// for this sample where the auth server and resource server are the same site,
// we use the same public/private key.
using (var signing = CreateAuthorizationServerSigningServiceProvider())
{
using (var encrypting = CreateResourceServerEncryptionServiceProvider())
{
var tokenAnalyzer = new StandardAccessTokenAnalyzer(signing, encrypting);
var resourceServer = new ResourceServer(_myUserService, tokenAnalyzer);
return resourceServer.GetPrincipal(httpDetails, requiredScopes);
}
}
}
}
The resource server is still missing
public sealed class MyResourceServer : ResourceServer
{
public override System.Security.Principal.IPrincipal GetPrincipal([System.Runtime.InteropServices.OptionalAttribute]
[System.Runtime.InteropServices.DefaultParameterValueAttribute(null)]
HttpRequestBase httpRequestInfo, params string[] requiredScopes)
{
AccessToken accessToken = this.GetAccessToken(httpRequestInfo, requiredScopes);
string principalUserName = !string.IsNullOrEmpty(accessToken.User)
? this.ResourceOwnerPrincipalPrefix + accessToken.User
: this.ClientPrincipalPrefix + accessToken.ClientIdentifier;
string[] principalScope = accessToken.Scope != null ? accessToken.Scope.ToArray() : new string[0];
// Now your own code that retrieves the user
// based on principalUserName from the DB:
return myUserService.GetUser(userName);
}
}
Next, modify web.config so DNOA doesn't complain about missing SSL connections in development:
<configSections>
<sectionGroup name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection, DotNetOpenAuth">
<section name="openid" type="DotNetOpenAuth.Configuration.OpenIdElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
<section name="oauth" type="DotNetOpenAuth.Configuration.OAuthElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
<sectionGroup name="oauth2" type="DotNetOpenAuth.Configuration.OAuth2SectionGroup, DotNetOpenAuth">
<section name="authorizationServer" type="DotNetOpenAuth.Configuration.OAuth2AuthorizationServerSection, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
</sectionGroup>
<section name="messaging" type="DotNetOpenAuth.Configuration.MessagingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
<section name="reporting" type="DotNetOpenAuth.Configuration.ReportingElement, DotNetOpenAuth" requirePermission="false" allowLocation="true" />
</sectionGroup>
</configSections>
<dotNetOpenAuth>
<!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. -->
<reporting enabled="true" />
<openid>
<provider>
<security requireSsl="false">
</security>
</provider>
</openid>
<oauth2>
<authorizationServer >
</authorizationServer>
</oauth2>
<!-- Relaxing SSL requirements is useful for simple samples, but NOT a good idea in production. -->
<messaging relaxSslRequirements="true">
<untrustedWebRequest>
<whitelistHosts>
<!-- since this is a sample, and will often be used with localhost -->
<add name="localhost"/>
</whitelistHosts>
</untrustedWebRequest>
</messaging>
</dotNetOpenAuth>
Related
Context: I am developing a client which will consume cxf soap webservice. At this moment, I only have the wsdl and its xsd's which are enough for generating the java types.
Requirement: I have to get the ContactType and I am sure we will receive it when the webservice be up-and-running (ContactType is just one sample among several others).
I searched in Eclipse by ContactType.java and I found it
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ContactType", propOrder = {
"telefoonnummer",
"faxnummer",
"gsm",
"email",
"website"
})
public class ContactType {
#XmlElement(name = "Telefoonnummer")
protected TekstKort20Type telefoonnummer;
...
#XmlElement(name = "Email")
protected Tekst20Type email;
#XmlElement(name = "Website")
protected Tekst20Type website;
...
The problem: I can't figure out which class consume it in order to code like MyWebServiceResponse.getMyAType().getMyBType.. so on until ContactType. It would be easy if the xsd tree was small or I know previously the model design (which isn't my reality).
Well, I know the type I will receive from webservices (let's called here getMyAType) and I can browse/navigate each object but it become a tremendous task done by eyes untill I found it one I have to read and populate a local pojo.
Doubt: why don't I find anywhere some code consuming/compsing ContactType? I manually searched by contact and I found:
#XmlRegistry
public class ObjectFactory {
...
public OndernemingMyCostumerAppType createOndernemingMyCostumerAppType() {
return new OndernemingMyCostumerAppType();
}
...
<xs:complexType name="OndernemingMyCostumerAppType">
<xs:sequence>
...
<xs:element name="Contact" type="ContactType" minOccurs="0"/>
...
</xs:sequence>
</xs:complexType>
I believe that a factory is interfering in the Eclipse tool Type Hierarchy and Call Hierarchy so Eclipse can show me which classes depend on ContactType (this would make my work easy).
My question: certainly it is a kind of common problem and I don't think JAXB/CXF experienced developers have been looking by eyes. Is there some smarter way to discover from botom class to up the tree dependency?
PS.: I can't get a xml sample answer so I could print it and control+F easialy in notepad. The server isn't yet up-and-running but I already have the wsdl+xsds.
Probably one of the most dummy question I have made but I really didn't find the answer anywhere before. Instead of "Type Hierarchy" or "Call Hierarchy" views, just searched by "References" is enough (don't forget to pick up generated_source folder). I hope this can help someone using Eclipse and creating a client to soap service someday.
I'm trying to invoke ProfileFormHandler's create handle using ATG rest client as shown below.
mSession = RestSession.createSession(mHost, mPort,"kim#example.com","password");
mSession.setUseHttpsForLogin(false);
mSession.login();
Map<String,Object> params = new HashMap<String,Object>();
params.put("value.login", "buddha#oracle.com");
params.put("value.email", "buddha#oracle.com");
params.put("value.password", "password");
RestResult result = RestComponentHelper.executeMethod("/atg/userprofiling/ProfileFormHandler","create",null,params,mSession);
I'm getting form exceptions that says, I'm not passing Login and Password Fields.
["Missing value for the required property Password",
"Missing value for the required property Login name"]
I've tried all combinations of login and password fields like value.login, Login, login, value.Login etc., but nothing seemed to work. All combinations giving the same form exceptions.
How do I invoke an ATG form handler using ATG REST Client and pass parameters to it?
Definitely need more information but looking at your code I can see that you have a value.login which is not configured ootb and believe this is causing the NPE. Assuming you have not customized the ootb ATG RegistrationFormHandler and the required field in the repository the only values you need to pass to the form handler are:
value.email
value.password
value.confirmPassword
value.firstName
value.lastName
Also, the help is specific that the data-type of the value property needs to be java.util.Dictionary
Add the following to /atg/rest/security/restSecurityConfiguration.xml
<resource component="/atg/userprofiling/ProfileFormHandler" secure="false">
<method name="handleCreate" secure="false">
<acl value="EVERYONE:read,write,execute" />
</method>
<property name="value.login" secure="false" />
<property name="value.password" secure="false" />
</resource>
I am very new to angularJS. I am searching for accessing services from RESTful API, but I didn't get any idea. How can I do that?
Option 1: $http service
AngularJS provides the $http service that does exactly what you want: Sending AJAX requests to web services and receiving data from them, using JSON (which is perfectly for talking to REST services).
To give an example (taken from the AngularJS documentation and slightly adapted):
$http({ method: 'GET', url: '/foo' }).
success(function (data, status, headers, config) {
// ...
}).
error(function (data, status, headers, config) {
// ...
});
Option 2: $resource service
Please note that there is also another service in AngularJS, the $resource service which provides access to REST services in a more high-level fashion (example again taken from AngularJS documentation):
var Users = $resource('/user/:userId', { userId: '#id' });
var user = Users.get({ userId: 123 }, function () {
user.abc = true;
user.$save();
});
Option 3: Restangular
Moreover, there are also third-party solutions, such as Restangular. See its documentation on how to use it. Basically, it's way more declarative and abstracts more of the details away from you.
The $http service can be used for general purpose AJAX. If you have a proper RESTful API, you should take a look at ngResource.
You might also take a look at Restangular, which is a third party library to handle REST APIs easy.
Welcome to the wonderful world of Angular !!
I am very new to angularJS. I am searching for accessing services from RESTful API but I didn't get any idea. please help me to do that. Thank you
There are two (very big) hurdles to writing your first Angular scripts, if you're currently using 'GET' services.
First, your services must implement the "Access-Control-Allow-Origin" property, otherwise the services will work a treat when called from, say, a web browser, but fail miserably when called from Angular.
So, you'll need to add a few lines to your web.config file:
<configuration>
...
<system.webServer>
<httpErrors errorMode="Detailed"/>
<validation validateIntegratedModeConfiguration="false"/>
<!-- We need the following 6 lines, to let AngularJS call our REST web services -->
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
</system.webServer>
...
</configuration>
Next, you need to add a little bit of code to your HTML file, to force Angular to call 'GET' web services:
// Make sure AngularJS calls our WCF Service as a "GET", rather than as an "OPTION"
var myApp = angular.module('myApp', []);
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
Once you have these fixes in place, actually calling a RESTful API is really straightforward.
function YourAngularController($scope, $http)
{
$http.get('http://www.iNorthwind.com/Service1.svc/getAllCustomers')
.success(function (data) {
//
// Do something with the data !
//
});
}
You can find a really clear walkthrough of these steps on this webpage:
Using Angular, with JSON data
Good luck !
Mike
Just to expand on $http (shortcut methods) here: http://docs.angularjs.org/api/ng.$http
//Snippet from the page
$http.get('/someUrl').success(successCallback);
$http.post('/someUrl', data).success(successCallback);
//available shortcut methods
$http.get
$http.head
$http.post
$http.put
$http.delete
$http.jsonp
For instance your json looks like this :
{"id":1,"content":"Hello, World!"}
You can access this thru angularjs like so:
angular.module('app', [])
.controller('myApp', function($scope, $http) {
$http.get('http://yourapp/api').
then(function(response) {
$scope.datafromapi = response.data;
});
});
Then on your html you would do it like this:
<!doctype html>
<html ng-app="myApp">
<head>
<title>Hello AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="hello.js"></script>
</head>
<body>
<div ng-controller="myApp">
<p>The ID is {{datafromapi.id}}</p>
<p>The content is {{datafromapi.content}}</p>
</div>
</body>
</html>
This calls the CDN for angularjs in case you don't want to download them.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="hello.js"></script>
Hope this helps.
I'm attempting to use capabilities provided by maven profiles to build customized builds for different server environments. What I'm attempting to do is combine maven resource filtering
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
with it's profile mechanism
<profiles>
<profile>
<id>mock</id>
<properties>
<application-url>http://mock-server-url</application-url>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
to convert this value in a file named server.cfg
${application-url}
to something I can use here:
public interface ServerResource extends ClientBundle {
public static final ServerResource INSTANCE = GWT.create(ServerResource.class);
#Source("server.cfg")
public TextResource server();
}
I can see that the value's been replaced in WEB-INF/classes but it doesn't appear that GWT used the file with the replacement to create the application javascript. How can I do this?
Using GWT compiler permutations to apply this kind of configuration is in my opinion a very bad idea. One of the most common complaints about GWT is the time it takes to compile, and by doing this you're just adding to the problem.
Configuration should usually be read from configuration files (surprise!), like shown here.
Anyway, what you're trying to do seems to me impossible. You cannot tell the client-side code to which server it should connect. This would violate the same-origin policy! The app can only communicate with the server it came from.
To have different apps running in different URLs, you would need to deploy several GWT apps with different names (even if they are basically the same). Then, you would just have to type the correct URL for each app (version) in the browser, and it will "look" at the right app. So you could have URLs like this:
http://myserver.com/app1
http://myserver.com/app2
In order to make a request to a different app running in the same server as the GWT application, you can do something like this:
String serviceUrl = "/app2/someService"; // or some other String sourced from a config file, using a GWT ClientResource for example
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET,
serviceUrl);
try {
// send request from app1 to app2
rb.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
log.info("Response: " + response.getStatusText());
// if response is 200 it's ok, you can read the outputStream to see what's in there
}
#Override
public void onError(Request request, Throwable exception) {
log.warning("Request Error", exception);
// do something more
}
});
} catch (RequestException e) {
log.warning("Request Exception", e);
// getting here means trouble with the connection or service!
}
I solved what I was trying to accomplish without the use of maven profiles or the GWT ClientBundle (which I never did get to work in the way I had intended when I wrote the question).
Here were the main issues I hoped to solve using maven profiles and the workaround I employed to solve the issue at hand:
Use Mock MVP Models in Hosted Mode
// inside the initialization for my model locator
boolean hostedMode = GWT.getPermutationStrongName().equals("HostedMode");
if (hostedMode) {
// instantiate mock models
} else {
// instantiate real models to call REST web services
}
Provide real models with correct RESTful server URL
I was able to accomplish this because my GWT app and the RESTful web service url follow a set naming convention. I basically strip the trailing '/' from the URL and append '_services"
String createServicesBaseUrl() {
StringBuffer baseUrl = new StringBuffer(GWT.getHostPageBaseURL());
int length = baseUrl.length();
baseUrl.replace(length-1, length, "_services");
return baseUrl.toString();
}
Enable testing of as much of the MVP Presenter (Activities & Places) as I could
I was already injecting the model locator into my Activity classes, so replacing that with a mock model locator for use by JUnit was straightforward. I did the same for my views and abstracted away some of the other code which didn't seem to work outside of the browser (like the GWT PlaceController).
All in all my build is much the same, but I learned how to gain a lot of flexibility in testing, configuring the server instance my GWT application connects with, and which model my application uses (dependent on hosted vs server mode).
I am trying to develop a method in my RESTful web service in Java to insert multiple entries into a MySQL DB using POST request. The generated RESTful Web Service has a method to insert a single entity, but not multiple ones. For example, it accepts:
<creature>
<sort>Mouse</sort>
<name>Pinky</name>
</creature>
But not (what I would like):
<creature>
<sort>Mouse</sort>
<name>Pinky</name>
</creature>
<creature>
<sort>Elephant</sort>
<name>Dumbo</name>
</creature>
I'm guessing that you have to loop through the entities, but not sure how to implement it, being a shameful novice.
Just ran into this myself. I need transactional posts of multiple items, so iterating on the client is out of the question. The consensus seems to be that you need to use a separate path from your normal resources:
http://chasenlehara.com/blog/creating-restful-web-services/ (Multi-resources)
RESTful way to create multiple items in one request
I couldn't find much about how to do this with Jersey, though. As it turns out, it's pretty easy. You should already have multi-entity converter and resource classes for GET requests, you just need to specify a path where the server can assume it's going to receive them:
#Path("creatures")
#Stateless
public class CreaturesResource {
...
#POST
#Consumes({"application/xml", "application/json"})
public Response post(CreatureConverter data) {
Creature entity = data.resolveEntity(em);
postCreature(entity);
}
#POST #Path("multi")
#Consumes({"application/xml", "application/json"})
public Response postMulti(CreaturesConverter data) {
Collection<Creature> entities = data.getEntities();
for (Creature c : entities) {
postCreature(c);
}
}
Then instead of posting
<creature />
to
http://.../resources/creatures
You would post
<creatures>
<creature />
<creature />
</creatures>
to
http://.../resources/creatures/multi