Contents tagged with REST

  • Subsequent calls to AcquireToken()

    Using the Active Directory Authentication Library (ADAL) and getting that annoying flash from the authentication dialog on subsequent calls? Maybe you’re creating a new AuthenticationContext every time? In that case the call to AcquireToke() by the context cannot keep and lookup the cached token and refreshtokens. You should try to keep a cached or static version of the AuthenticationContext alive between calls. Something like this of you’re calling a web api or similar:

    private static readonly AuthenticationContext AuthenticationContext = new AuthenticationContext("https://login.windows.net/domain.com");

    private static AuthenticationResult GetAuthenticationToken()
    {
    var acquireToken = AuthenticationContext.AcquireToken("https://domain.com/WebApp-something.azurewebsites.net", //resource id of the web api
    "acca2f90-5f76-45b5-8ec3------", //the client id
    new Uri("https://domain.com/YourClientRedirectUrl")); //client redirect url

    return acquireToken;
    }

    public static async Task<string> GetRequestAsync(string requestUri)
    {
    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
    var authorizationHeader = GetAuthenticationToken().CreateAuthorizationHeader();
    request.Headers.TryAddWithoutValidation("Authorization", authorizationHeader);
    var response = await client.SendAsync(request);
    var responseString = await response.Content.ReadAsStringAsync();
    Debug.WriteLine(responseString);
    return responseString;
    }

  • Secure ASP.NET Web API with Windows Azure AD

    Note that the APIs, tools and methods change quickly in this area, this blog post will get old and die eventually…

    Many organizations now look at the Azure environment to host their websites and web APIs, and some decide to move their mail and Active Directory too. Now with the latest updates and previews in Azure, you’re able to secure your web APIs with Azure AD. Vittorio Bertocci wrote an article for MSDN Magazine about Secure ASP.NET Web API with Windows Azure AD and Microsoft OWIN Components and it worked fine up until a couple of weeks ago when things moved around in these parts of Azure Smile

    I will try to describe in detail how to secure your web API with Azure Active Directory now, using Visual Studio 2013 and the preview of ADAL (Active Directory Authentication Library) package.

    Create a web API project

    Fire up Visual Studio and create a new ASP.NET Web Application. I’m calling mine “johandanforth”, I’m selecting “Web API” and click the “Change Authentication”

    image

    In the next dialog, click “Organizational Account” and enter the domain of your Azure AD tenant, in my case it’s “irm.se”:

    image

    After you press “OK” you’ll be asked to login with your Azure AD account, then “OK” again and Visual Studio will create a web application resource in your Azure AD. Now look it up in the Azure Management application. Note that you may have to log out and in again or restart the Azure management web app to see the newly created application.

    In my case the application has been named “johandanforth” and is for securing your development project on localhost. The SIGN-ON URL (also called the APP URL in the management application) is https://localhost:44310/ which can be seen both on the applications overview and if you click on the application and go to the CONFIGURE “tab”:

    image

    The sign-on url should be the same as where the web API is hosted, in this case the same localhost-settings as you got in the development project web-settings.

    Open up web.config of your web API project and have a look at these settings:

        <add key="ida:Audience" value="https://irm.se/johandanforth" />
        <add key="ida:ClientID" value="d169beb7-34bc-441b-8b93-87e3181a1132" />

    The “ida:Audience” in web.config correspond to the value of APP ID URI of the application resource in the management portal and the “ida:ClientID” correspond to the CLIENT ID in the portal.

    image

    Update the web application manifest

    Before you any application can access this resource, we must update the “manifest”. Still on the CONFIGURE tab for your web API resource, there should be a MANAGE MANIFEST menu option down at the bottom toolbar. Click it and select “Download Manifest”. It’s a json-text-file, and should save it somewhere where you know is, because we will add a section to it and then upload it again using the same menu option:

    image

    Open the json-manifest and replace the "appPermissions": [], section with this:

    "appPermissions":[
    {
    "claimValue":"user_impersonation",
    "description":"Allow the application full access to the service on behalf of the signed-in user",
    "directAccessGrantTypes":[

    ],
    "displayName":"Have full access to the service",
    "impersonationAccessGrantTypes":[
    {
    "impersonated":"User",
    "impersonator":"Application"
    }
    ],
    "isDisabled":false,
    "origin":"Application",
    "permissionId":"b69ee3c9-c40d-4f2a-ac80-961cd1534e40",
    "resourceScopeType":"Personal",
    "userConsentDescription":"Allow the application full access to the service on your behalf",
    "userConsentDisplayName":"Have full access to the service"
    }
    ],
     
    At the moment, there doesn’t seem to much in way of documentation on this manifest file, but it should work without modifications. I’ll try to write something about this manifest file as soon as I get some more docs on it.
     
    Next thing you do is upload the modified manifest file. Note that the portal may give you an error message during upload, but things seems to work anyway! It may look like this:
    image

    Create a client

    Now let’s try and access the sample ValuesController Web API in your development environment using a web browser, Fiddler or similar. In my case it’s https://localhost:44309/api/values and you should get a HTTP/1.1 401 Unauthorized error back. To be able to access the protected resource, you must add a client resource in the AD and configure it to access the web API.

    If you are not there already, in the Azure management portal, go to Active Directory, click on your domain name and select the APPLICATIONS tab. Then click the ADD-icon down the center of the bottom toolbar. Then go ahead and select “Add an application my organization is developing”:

    image

    Enter a name for your client (I’m going with “johandanforth-client”, and make sure you select NATIVE CLIENT APPLICATION because we’re going to write a simple Windows WPF client to call our web API:

    image

    On the second page, type in a redirect url for your client – it can be anything as long as it is a valid url. I’m going with https://irm.se/johandanforth-client.

    image

    Your client is now created, but the last step to do is to give permission to our web API. Scroll down to the bottom of the client application CONFIGURE page and look at the “permissions to other applications (preview)” section. In the dropdown marked “select application” you should be able to see and select your web API. You must also select the “Delegated permissions” dropdown and mark the only option available for you. As you can see, the description matches the text in the manifest file:

    image

    Remember to SAVE!

    Almost there, hang on…

    Create a Windows WPF application for testing

    Add a new Windows WPF Application to your solution, I’m calling it “johandanforth.client”, and create a button with a click-event or something to hold the code that will authenticate and get values from your API. Bring up NuGet and search for “ADAL”, make sure you have “Include Prerelease” selected:

    image

    Install the prerelease package from February 2014 (it will probably be updated soon), then paste this code into the click-event of that button you created earlier:

    using System;
    using System.Net.Http;
    using System.Windows;
    using Microsoft.IdentityModel.Clients.ActiveDirectory;

    namespace johandanforth.client
    {
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
    InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
    //this is to accept dev certificates - do not use in production!
    System.Net.ServicePointManager.ServerCertificateValidationCallback = ((a, b, c, d) => true);

    var ac = new AuthenticationContext("https://login.windows.net/irm.se"); //ad domain = irm.se

    var ar1 = ac.AcquireToken("https://irm.se/johandanforth", //app id uri of the web api
    "91b4bc31-92c2-4699-86f5-fa84a718da30", //the client id
    new Uri("https://irm.se/johandanforth-client")); //the client redirect uri

    var authHeader = ar1.CreateAuthorizationHeader();

    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44310/api/values");
    request.Headers.TryAddWithoutValidation("Authorization", authHeader);
    var response = await client.SendAsync(request);
    var responseString = await response.Content.ReadAsStringAsync();
    MessageBox.Show(responseString);
    }
    }
    }

    There are a few lines that must be change to work with your sample code. First change the AuthenticaitonContext to match your Azure AD domain/tenant name:

    var ac = new AuthenticationContext("https://login.windows.net/irm.se");
    

    Next look at the code part which acquires a token – this is when the login dialog pops up and asks the user to log in using his or hers organizational account. This line corresponds to the web API uri, which is the same as the “ida:Audience” in your web.config file, so update it to match that value:

    var ar1 = ac.AcquireToken("https://irm.se/johandanforth",  

    The next line is the client id of the application client you created in Azure AD, look it up and change the id accordingly:

    "91b4bc31-92c2-4699-86f5-fa84a718da30",

    The last line is the redirect-uri of the client, look it up on the same page in the Azure management portal:

    new Uri("https://irm.se/johandanforth-client"));

                  

    You must also modify the line with the call to the web API method to match your web server localhost settings:

    var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44310/api/values");

    Now, start the web API program in debug mode and wait until you see the Home Page, then right click and start debug of the WPF client. Click the button and you should be prompted to log in with your organizational account (this is the look of it in Swedish):

    image

    After a successful login, the code continues and you should be greeted with this:

    image

    Still with me?

    Deploy to Azure

    This is all well and good (hopefully), but we want to deploy our web API to Azure and run our clients against it in the cloud. To do that we need to:

    1) Create a web site to host our web API in Azure

    2) Publish our code to the site

    3) Create an Azure AD resource for the web API (VS does this for you)

    4) Modify the manifest for the web API (like before)

    5) Give the client permission to the new resource (like before)

    6) Update web.config and the client code to match the IDs and URIs of the new resources (ida:Audience == APP ID URI == the resource you want to access)

    7) Publish the code again (to get the updated web.config uploaded)

    8) Run!

    Here’s some quick shots of some of the steps. First create a web site in Azure by selecting “WEB SITES” in the left hand menu of the Azure Portal, press the big plus-sign down in the corner and create a custom web site. I’m calling mine “johandanforth” (ignore the error message Winking smile )

    image

    Now go back to Visual Studio, right click the web API project and select “Publish…”.

    image

    Press the “Import…” button to download and import the publishing profile of the web site you created, and select the newly created Web Site in the dropdown. Click OK.

    image

    You have to authenticate one or two times to get past these steps, but should finally get to the last step of the Publish process:

    image

    When Visual Studio is done publishing, a browser page will open up with the Home Page showing:

    image

    Visual Studio should now have created a new application resource in the Azure Active Directory, so get back to the portal and have a look at the list of AD applications. A resource named “WebApp-xxxxxxxxx.azurewebsites.net” should be listed there. Note – you may have to sign out and sign in to the portal to show the web api resource. This has happened to me a couple of times!

    image

    Click on the resource and look at the details in the CONFIGURE tab.

    image

    Copy the name of the “APP ID URI” and past it into the “ida:Audience” value in the web.config file of your web API project in Visual Studio:

        <add key="ida:Audience" value="https://irm.se/WebApp-johandanforth.azurewebsites.net" />

    The same value must also be updated in the WPF client:

    var ar1 = ac.AcquireToken(https://irm.se/WebApp-johandanforth.azurewebsites.net,  

    You must also (of course) update the call to the web API method to point at the web site in the cloud:

    var request = new HttpRequestMessage(HttpMethod.Get, "https://johandanforth.azurewebsites.net/api/values");

    We’re not done yet though… now you have to do the same steps you did for the localhost resource earlier - download and update the manifest file for the web API resource and give the client resource permission to use the service.

    Finally (yes finally) – publish the web API project again to get the updated web.config file to the cloud site!

    Once the code is published, you should be able to run the client successfully.

    Please give feedback if you have problems with any step/s of this walkthrough. Other questions, bugs and such is better asked on the Windows Azure Active Directory forum. I’m still learning these things and trying to keep up with the changes Smile

  • Please Feedback! Unity, nHibernate, Fluent, Linq... Trying New Architecture Combinations

    We're thinking about a new architecture for a set of pretty large WCF (and perhaps also REST) services that's going to be developed during the next year and perhaps you dear reader would like to comment!

    The services themselves are pretty straight forward, we're going to serve data from a huge SQL Server database which unfortunately is old and lacks relationship/fk/pk between most tables. Nothing we can do about that I'm afraid but we thought that nHibernate could be a good way to map data to domain objects. Some of the services will need to handle more complex business rules, but no heavy computing or long running stuff (not atm anyway).

    What more can I say... everything is going to be running on .NET 3.5, and we have a pretty good view of the business domain, we're currently modelling the information/domain together with the customer and we will probably be developing the whole thing in a DDD-ish way, using unit and integration tests, IoC...

    So, currently we're thinking of WCF/REST for the service layer, Unity as container and building something around nHibernate for the Repository (looking at the IRepository implementation in Fluent). We're new to nHibernate but have been looking at nHibernate.Linq which looks really nice, and I think we'll use the Fluent API and map the classes in code instead of using XML configuration (which I'm allergic against). Just have to figure out a good way to make it all fit together, especially to get a decent UnitOfWork to work with the nHibernate session and the repository. I'll see what I come up with and post it here.

    Ideas? Please comment or send me an email of you like.

  • Returning Json from RESTful Interface with WCF

    WCF2 Someone commented on an earlier blog post I did on REST, POX/POJO and WCF and the comment read:

    How about REST WCF bits from .NET 3.5 SP1? Is it possible now to let the user decide in which format he wants the response (xml or json) like MySpace API for example?

    The convention is to use a file like extension at the end of the resource to specify data return type (.xml or .json)

    api.myspace.com/.../details.xml

    api.myspace.com/.../details.json

    UPDATE/EDIT: Turns out I was doing this the hard way as there is support for json serialization right from the ServiceContract which makes this extremely easy. Just make sure to specify the ResponseFormat to be json. In a previous "version" of this blog post, I used the JavaScriptSerializer class, which is... dumb :)

    First go take a look at the sample that Kirk Evans had on his blog.

    Note that it may be easier to create a RESTful interface with ASP.NET MVC if you're into that tech, but that's another blog post.

    So, first I'm modifying the REST interface somewhat, adding support for /details.xml and /details.json URI:

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet(UriTemplate="customers/{id}/details.xml")]
        Customer GetCustomer(string id);
    
        [OperationContract]
        [WebGet(UriTemplate = "customers/{id}/details.json", 
    ResponseFormat=WebMessageFormat.Json)]
    Customer GetJsonCustomer(string id); }

    As you can see, on the GetJsonCustomer() method, I'm specifying the ResponseFormat to be json. That's it :)

    A sample implementation for this interface looks like this:

    public Customer GetCustomer(string id)
    {
        return new Customer { ID = id, Name = "Demo User" };
    }
    
    public Customer GetJsonCustomer(string id)
    {
        return GetCustomer(id);
    }

    Using Fiddler to simulate client request and see what comes out of our RESTful service, we get this result from the /customers/123/details.xml request:

      <Customer xmlns="http://schemas.datacontract.org/2004/07/RESTfulWCF" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ID>1</ID><Name>Demo User</Name></Customer>

    ...and this from the /customers/123/details.json request:

      {"ID":"123","Name":"Demo User"}

  • Why Developers Are Interested in REST

    I had a laugh when I saw James Kovacs' blog post abot Why Developers are Interested in REST:

    I'm doing some WCF work for a client, specifically around WS-Security. I stumbled upon the System.ServiceModel.MessageSecurityVersion class today. Its static properties alone should explain why developers are craving simpler technologies like REST...

    I think he's got a point there actually. Web services with WCF can be very easy to use, and it can be so very complex it'll get your head to spin. The REST and POX/POCO style of services is definitely getting more attention, even from within Microsoft. WCF now supports RESTful interfaces, and we've seen REST-related demos by well known Microsoft presenters several times now, especially around WCF, EF and Astoria/ADO.NET Data Service. Also, it's very easy to create a RESTful service with ASP.NET MVC. We saw several REST-related presentations at Mix07 and Mix08 and I'm sure there will be a lot of REST/POCO/POX/Atom demos at PDC later this year.

    Ofcourse there will be a number of situations and type of applications which require a more complex protocol than what REST can offer, but as a developer and software architect who prefers simple solutions, I just love the simplicity of it all. Or maybe I'm just old and smilingly recognize old techniques coming back again - we did XML on (S)HTTP with ASP years and years ago, didn't we? And it worked pretty darn well I can tell you ;)

    The "REST effect" is perhaps the result of the WS-* race, which in my opinion exceeded the speed limit a long time ago. It's just impossible for an average human beings to keep up with it unless you want to become a WCF/WS expert and do nothing much else, which is not an option for me. I know, there are people out there, like my colleague Eric, who groks it all, but he's not human ;)

  • More on RESTful Service with WCF and POX/POCO

    Kirk Eveans wrote a blog post about Creating RESTful Services Using WCF, which gives you a good understanding of how to get started with REST on WCF. In his sample, Kirk has 2 methods in a REST interface:

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet(UriTemplate = "customers/{id}")]
        Customer GetCustomer(string id);
    
        [OperationContract]
        [WebInvoke(UriTemplate = "customers")]
        Customer PostCustomer(Customer c);
    }

    The Data Contract for Customer looks like this:

    [DataContract(Namespace = "")]
    public class Customer
    {
        [DataMember]
        public string ID { get; set; }
        [DataMember]
        public string Name { get; set; }
    }

    Kirk also describes how to use the Fiddler tool to send REST request to the service, which is a wonderful tool for these circumstances.

    Now, to get the customer with ID 123, just send a GET request to the url: http://127.0.0.1:8000/customers/123 and the service will return:

    <Customer>
    <ID>123</ID>
    <Name>Demo User</Name>
    </Customer>

    To call the other method, PostCustomer(), send a POST request to http://127.0.0.1/customers with the following request body:

    <Customer>
    <ID>123</ID>
    <Name>Demo User</Name>
    </Customer>

    This returns:

    <Customer xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ID>123</ID>
    <Name>Hello, Demo User</Name>
    </Customer>

    NOTE: Remember that you must add a HTTP header, specifying the content type, or the POST request will fail (Content-Type: application/xml).

    Wrong Order of Nodes?

    But what if the programmer sends the <Name> node before the <ID> node? Like this:

    <Customer>
    <Name>Demo User</Name>
    <ID>123</ID>
    </Customer>

    The service will then return:

    <Customer xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ID i:nil="true"/>
    <Name>Hello, Demo User</Name>
    </Customer>

    Note that the ID is null! If the ID was declared as an integer in the Data Contract, the response from the service would be:

    <Customer xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ID>0</ID>
    <Name>Hello, Demo User</Name>
    </Customer>

    Note that ID is 0 (zero), which could become a somewhat hard bug to catch. I asked Kirk about this and he confirmed the reason for this behaviour is the way the DataContractSerializer works. If no order is specified in the DataContract, it will (de)serialize in alphabetic order. If this is a problem for you, there is away around it by specifying the XmlSerializerFormat attribute on the REST interface:

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebGet(UriTemplate = "customers/{id}")]
        [XmlSerializerFormat]
        Customer GetCustomer(string id);
    
        [OperationContract]
        [WebInvoke(UriTemplate = "customers")]
        [XmlSerializerFormat]
        Customer PostCustomer(Customer c);
    }

    POCO Support in SP1

    One of the new features in .NET 3.5 SP1 is the support for POCOs - the DataContractSerializer supports serializing types that doesn't have the [DataContract] or [Serializable] attributes. Aaron Skonnard has a good post on this. This means you can safely get rid of the attributes on the Customer class:

    public class Customer
    {
        public string ID { get; set; }
        public string Name { get; set; }
    }

    Note that the DataContractSerializer is still picky about the XML it gets to be able to deserialize it properly. Again, to get a more "relaxed" REST interface where WCF accepts the Name and ID nodes in any order, use the XmlSerializerFormat. I'm not sure this is what you want, but it's an option.

    I had a short mail conversation with Kirk about this, and he raised an interesting question about the lack of a industry accepted standard for describing RESTful services and I think he's right there. The XML-node order wouldn't be a problem at all if I gave the client programmer a schema or a contract which specified exactly how the RESTful interface was to be accessed and in which order the XML-nodes must come. Kirk had a lot to say about this, and I do hope he writes up a blog post about his thoughts ;)

    There are ways to send and receive any XML to a RESTful interface with WCF, and I'll write a blog post about that another day.

  • Building Web Services the REST Way

    There is much talk at the moment about REST, what is it and not is, Lo-REST, Hi-REST and whatnot. For those of you who don't really know what REST is and don't have time (or like me, not the brain) to delve into Fielding's full REST description, Roger L. Costollo wrote a short piece called Building Web Services the REST Way, which I think is pretty good. Some of you will recognize the REST style from XML on HTTP solutions you did 5-6 years ago, before the dawn of the SOAP and ROPE...

    It seems to me that some people think Microsoft is not supporting HTTP/XML/REST the way it should. If you want to get updated on the matter, go to Don's blog and Jonnay's blog (Sacrificial Rabbit) and start to read.