We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Ember & SOA: Stumbling towards SOA

00:00

Formal Metadata

Title
Ember & SOA: Stumbling towards SOA
Subtitle
The story of CloudHDR
Title of Series
Number of Parts
20
Author
License
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
A breakdown of the general architecture that was used for building CloudHdr. The entire system is composed of 3 main "service" apps, and a collection of Ember apps each aimed at a different vertical slice of user facing functionality. Topics include auth from the Ember apps to services, cross domain issues for data transfer, and handling file uploads.
VideoconferencingCorrelation and dependenceService-oriented architecturePresentation of a groupService (economics)AuthenticationComputer fontContext awarenessGreen's functionRange (statistics)Process (computing)AutomorphismFormal languageDynamic rangeContext awarenessMobile appDigital photographyService-oriented architectureType theoryInformationMereologyDemosceneBitPhysical systemCartesian coordinate systemPoint cloudGroup actionIntegrated development environmentSelf-organizationDecision theoryMeasurementCovering spaceSystem callWebsiteLatent heatOptical disc driveNear-ringSet (mathematics)FreewareXMLComputer animation
Process (computing)Graph coloringDigital photographySeries (mathematics)
Mobile appSign (mathematics)Single-precision floating-point formatCodeMaxima and minimaType theoryVariety (linguistics)Mobile appCodeService (economics)Maxima and minimaRoboticsForm (programming)Single sign-onSingle-precision floating-point formatMashup <Internet>MereologyVariety (linguistics)Sign (mathematics)Integrated development environmentType theorySquare numberBuilding
Configuration spaceService (economics)Uniform resource locatorIntegrated development environmentCASE <Informatik>Mobile appVariable (mathematics)Figurate number
Computer fileConfiguration spaceNamespaceCodierung <Programmierung>Dependent and independent variablesGame controllerEndliche ModelltheorieComponent-based software engineeringGame controllerComputer fileDependent and independent variablesUniform resource locatorGraph (mathematics)Software developerIntegrated development environmentCodeInformationVariable (mathematics)AuthenticationConnectivity (graph theory)Endliche ModelltheorieRoutingTemplate (C++)CodeCycle (graph theory)BitNormal (geometry)Mobile app
LoginFacebookAuthenticationStandard deviationAuthorizationSign (mathematics)Error messageCodeAuthenticationService (economics)FacebookWeb browserInteractive televisionClient (computing)DiagramLoginMultiplication signBitWeb 2.0Power (physics)Message passingPoint (geometry)Cartesian coordinate systemMobile appOrder (biology)PasswordInternet service providerRoutingInformationInformation retrievalNormal (geometry)Figurate numberRow (database)Address spaceComputer configurationStandard deviationAuthorizationOpen setForm (programming)Associative propertyWeb pageSign (mathematics)EmailTerm (mathematics)Digital photographyError messageWebsiteCodeServer (computing)CASE <Informatik>Uniform resource locatorService-oriented architectureDiagram
Function (mathematics)Electric currentError messageError messageCodeAuthenticationAuthorizationObject (grammar)Point (geometry)Functional (mathematics)Uniform resource locatorCartesian coordinate systemMultiplication signMobile appInformationQuery languageGauß-FehlerintegralData storage deviceService (economics)CodeSet (mathematics)
Token ringSign (mathematics)Local ringAuthenticationLoginChemical equationService (economics)Validity (statistics)Client (computing)SequencePattern languagePoint (geometry)Line (geometry)Local ringGraph (mathematics)Data storage deviceDiscrete groupToken ringDependent and independent variablesInternet service providerWeb browserSoftware testingSign (mathematics)Form (programming)Web pageMobile appStructural loadBitComputer animation
Time domainElement (mathematics)Web browserLimit (category theory)Process (computing)View (database)Parameter (computer programming)Price indexVideo game consoleComputer fileSource codeComputer networkRouter (computing)WebsiteService (economics)Content (media)Computer configurationService (economics)SoftwareVideo gameComputer fileIntegrated development environmentDefault (computer science)Software developerDomain nameVirtual machineWebsiteWeb browserMessage passingGame controllerBitScripting languageServer (computing)Configuration spaceCartesian coordinate systemShared memoryVideo game consoleDisk read-and-write headRouter (computing)Dependent and independent variables
EmailHTTP cookieDependent and independent variablesComputer-generated imagerySource codeElement (mathematics)Computer networkVideo game consoleOpen setWebsiteEmailDependent and independent variablesGame controllerOpen setAuthenticationSet (mathematics)Domain nameRouter (computing)HTTP cookieXML
Function (mathematics)Computer fileComputer networkSource codeElement (mathematics)Query languageDefault (computer science)HTTP cookieComputer configurationObject (grammar)Wechselseitige InformationError messageFunktorVacuumDependent and independent variablesEmailComputer-generated imageryVideo game consoleAuthenticationSoftwareHTTP cookieObject (grammar)Query languageComputer configurationDefault (computer science)Web browserDependent and independent variablesBasis <Mathematik>Multiplication signVideo game console
AuthenticationRhombusOpen setInformationDecision theoryTrailPhysical systemXMLUML
Transcript: English(auto-generated)
Hi, everybody. Today I'm talking about Ember and SOA.
This is going to cover ways that you might adapt Ember into a service-oriented architecture type of an environment. In some ways, I think a better title for this talk is Stumbling Towards SOA, The Story of Cloud HDR. And the reason this is a better title, I think, is that SOA isn't a specification.
There's not an RFC that you can read and go implement. It's more of a way of thinking about designing applications and systems of applications. And the decisions that you make are going to be highly dependent on what your requirements are and what you hope to get out of it. So this is the story of some things that I've done
and some goals that I've set and the ways that I worked to meet those goals. It's really the story of me taking an app that looks kind of like this, a big monolithic Rails app, and turning it into a collection of apps that all work together to reach the same goal.
So here's what we're going to look at today. We're going to look at what are the first steps that you need to take to get started doing SOA with Ember apps. Then we're going to look at how authentication works in this type of an environment. And then finally, we're going to look at how you deploy these things out into a live environment. But of course, we actually need
to start counting at zero. And we need to look at a little bit of context and talk about goals and requirements. So first, a little bit about me. My name is Jeremy Green. Here's some things that I'm into, drumming, coding, entrepreneurship, photography, brewing. I'm also one of the organizers of the OKC Ruby group.
Here's some ways that you can contact me. If you have any questions or criticisms of this, feel free to tweet me or email me. And you can check out my website, octolabs.com. So Cloud HDR is an HDR photo processing automation app. And what HDR stands for is high dynamic range.
And dynamic range is the measurement between the lightest part of a scene and the darkest part of a scene when you're taking a photo. Knowing that really isn't all that informative. So a better question is, why HDR? And the reason that you want to do HDR is because when you take a photo, you really don't want either one of these.
The one on the left is kind of overexposed for the sky, but the foreground and the ground looks great. But then the one on the right, the sky looks nice, but the foreground is underexposed and it's very dark. So instead, you want to end up with something like this, where everything is exposed well in the sky
and on the ground, and you've got a lot of detail, a lot of really good color. So HDR is a process for taking a series of less than optimal photos and combining them into something that's a little more attractive. So first thing we need to talk about is what are the goals and requirements of moving into an SOA environment?
For me, my main goal is to have small focused apps. I wanted to have little tiny apps that I could test well that didn't have a lot of concerns leaking from part to part. Wanted to have single sign-on and single sign-off for users and I wanted to minimize code duplication.
In particular, I didn't want to have to build sign-in forms into each one of my Ember apps. I want to support a variety of apps and service types. I need some that are just vanilla Rails and some that would be Ember apps and some that are kind of a mash-up of Rails app with Ember on top of it.
And I want it to be friendly to people and robots. So the first step is getting started. It's really pretty much a walk in the park. First thing you do is just start up a local service. You know, in my case I'm using Rails. I built a very simple Rails app that is just a JSON API.
And then you configure Ember data to know how to find that. So, you know, just in your rest adapter you're setting the host to be whatever your, the location of that service is. Better than hard coding it, I like to rely on environment variables to hold the information about where to look.
So for local development you could just export it or maybe you set up a .env file. And then you're gonna configure your build tools to allow you to pull from that environment variable to set up your host. It's worth noting that you need to be careful about response codes for JSON requests.
You wanna be sure that you send meaningful response codes and aren't just issuing a redirect to some other place. The reason for that is that within Ajax requests it can't follow the redirect. And so if you issued a redirect you'd have to have some code in there
that inspects the response code, checks to see if it's a 302. If so, you might need to inspect the location that it's trying to redirect you to. For some URLs you might want to actually follow the redirection. For other URLs you might not want to. So it's a little messy.
It's better if you can just send a 401 unauthorized so that your code can respond to it easily. And from there you pretty much just proceed as normal. For your Ember app you're gonna do all the normal stuff, set up routes, controllers, models, components, templates, just your normal development cycle.
So congratulations, once you get that far you are now doing SOA. So the next bit is authentication. And this comes into play really pretty early because you're not gonna get very far down the road before it becomes important to know which user is interacting with your system so that you can, in my case,
associate the photos that they upload with their account and keep them separate from photos that are uploaded by other users. So we can look at how login with Facebook works to get an idea of how to do this. And it's not that we're gonna use login with Facebook to handle authentication for our app.
It's just that that's a method that people are pretty familiar with in terms of distributed authentication. When you enable login with Facebook for your site, you're not asking somebody to give you an email and a password in order to log in. You delegate that to Facebook and let Facebook figure out what's their email address.
Is the password correct? And then they just get redirected back to your site as that user. And so we can use the same technology that Facebook uses and that's OAuth. And OAuth is an open standard for delegated authorization. This is what powers most of the login with whatever options
that you see anywhere on the web, whether it's login with Twitter, login with GitHub, login with Facebook, et cetera. So let's take a brief look at how OAuth works. This'll be an intro if you're not familiar with it or if you have seen this before, it'll be a very brief review.
So let's say that you've got a client who wants to get some things on the web. They issue a get to some protected resource on your server and your server says, oh wait, you need to be logged in to see this, I can't let you see it just yet. So instead of sending them to a please sign in page,
what happens is that they get a redirect, browser does what it's supposed to do, follows the redirect, and you end up at the OAuth provider. The OAuth provider at this point is gonna ask you to sign in by sending a sign in page. This is displayed in the browser, the user can fill out the form, do what they need to do,
then eventually that form's gonna get posted back to the OAuth provider. The provider is going to verify the credentials and if everything works and the user is able to log in, then the OAuth provider is gonna redirect back to the original service,
and then at that point the service is gonna know, okay, this person is logged in and I can show them this top secret information. So here between the service and the OAuth provider is where OAuth happens, and these diagrams are very simplified. There are a lot of redirects happening in there
that I'm not showing just because it's kind of outside the scope of this discussion. If you're interested to know about how it works, it looks something kind of like this, but not really. I'll be speaking at RailsConf next month about service-oriented authentication where I'll go into some more details about how all of this OAuth stuff works
if you're interested. So the next thing to know is how does Ember interact with OAuth? And the answer is that we're just basically doing regular OAuth, setting up session-based authentication for our JSON API services. So this looks a little something like this.
The client is gonna issue a get to the Ember application. The application is gonna return the Ember app. That's gonna get loaded up in the browser. At this point, you could opt to give the user a loading message or a we're logging you in message, something that lets them know what's happening.
At that point, the Ember app will try to retrieve some data from the API provider, and the provider will return a 401 Unauthorized saying this user is not allowed to access this resource. So at that point, the Ember app will redirect
to a specific URL on the API service that is responsible for setting up the authentication. At that point, the API is gonna redirect again to the OAuth provider where, again, the OAuth provider
is gonna eventually deliver to the browser just a sign-in form, ask the user to sign in. Once the user's filled out their form and posted that back to the OAuth provider, again, the redirect is gonna happen. They're gonna get returned to the API service which will then start their session,
log them in, and then eventually redirect back to the Ember app. This will be loaded in the browser, and then at this point, the user can interact with the app as normal. Data requests to and from the API service will work because it's all happening within a session.
So what does the code look like for the Ember app? There are really only two bits of this. First is just to retrieve some data. It could be some data that you try to retrieve immediately as soon as the app is ready, like trying to get a user record, or it could just be normal data retrieval
that needs to happen within your app based on whatever route the user's trying to hit. The next bit is just need to handle authorization errors. So the first bit is pretty easy. The way I do it is when the app is ready, I just try to get information
about who is the current user. I do this by registering a ready function in my application create method that just gets ahold of the data store, tries to look up the user by ID, and if it finds it, then it sets that in a variable on the app.
Handling authorization errors is also pretty easy. Inside of where you set up your application adapter, and I'm extending off of the Ember data REST adapter, I just register a custom Ajax error function. And what this function does is any time there's an Ajax error,
it's gonna inspect the jQuery XHR object that comes back, look to see if the status code is 401, and if so, then it builds a new location that is the URL for the authentication point on the API service, and then it's gonna set document.location to be the new location,
and that achieves the redirect. Another way that you might go about this is using token-based authentication. I have to say that I haven't actually implemented this yet. It's something that I've started to toy with and have run a couple of local tests, but I haven't deployed it, so your mileage may vary on how all this works for you.
So the basic path that's gonna happen here is, again, the client's just gonna request the Ember app. The Ember app's gonna get loaded into the browser and start working. From there, the Ember app is gonna check in the local store to see if there's an authentication token that it can use.
Since we're assuming that the user has not signed in yet, at this point, there's no token. So then, the Ember app needs to redirect them to the OAuth provider itself. At this point, we're skipping the step of redirecting to the API service first. We're just going directly to the OAuth provider.
The OAuth provider's again gonna return a please sign in page that's gonna have a form for the user to fill out. Once the user has completed the form and is ready to sign in, they're gonna click the sign in button. That's gonna go back to the OAuth provider. And at this point, they're gonna be redirected again. During this redirect sequence,
the OAuth provider could write the token into the local store so that it's then available for the Ember app. The browser's gonna follow that redirect, end up back at the Ember app. It's gonna load into the browser and start working. At this point, the Ember app,
when it looks to find an authentication token in the local store, it'll find it. And at that point, it can send a get to the API service to retrieve some data. At this point, the API service needs to authenticate that token to make sure that it's a valid one. So it's gonna send a request to the OAuth provider
to verify the token. Assuming that it's a valid token, the OAuth provider is gonna respond with 200 OK. And then that's gonna tell the API service that it's okay to allow the user to see that data. So that's the overview of how a token-based authentication would work.
So the next bit is leaving localhost. And this is all about how do you deploy this stuff off of your development machine and into a live environment. There are a couple of tricky things that come up here that you don't encounter when you're just developing locally that you do need to know about when you go to deploy.
And these are all cross-domain issues. I'm hosting each of my services at subdomain of my main domain. And by default, some things just don't work across subdomains unless you take steps to allow them to work. So the first thing I ran into was I would see this in the network tab
where it would say that a request had been canceled. I didn't really know what that meant. And confoundingly, when I went to look in my Rails console, I would see that the request had made it to the API service.
The API service had done what it needed to do and returned a 200 OK. As far as the server was concerned, everything was fine. After just a little bit of head scratching, I finally remembered that I should check the JavaScript console and I found a message about the request not being allowed by the access control allow-origin.
Luckily, there's a good tool that allows us to fix this problem. It's called CORS, but not that CORS. It's cross-origin resource sharing. And what this is is just a way that allows a site to tell browsers that it's willing to provide content and services to other sites.
In Rails, this is real easy to set up. There's a gem called Rack CORS that you add to your gem file. And then in application RB, you do just a little bit of configuration to tell it which origin domains are allowed, what resources they're allowed to access with what headers and with what methods.
So once you do that, in the response headers, you'll see a bunch of new headers that get set. All of these relate to access control. And when you have that, then it'll start to allow your requests to work.
If you wanted to make a public open API that doesn't need authentication, you might do something like this for your CORS settings that just tells it allow any headers and you probably only wanna just do a get method. You probably really don't wanna do this. You don't want to allow any methods on any resource from any domain.
If you think that you need to do this, I would encourage you to learn about cross-site scripting and realize why this might be a bad idea. Maybe you do need to do it, but if you do, you're gonna need to take some other precautions to make sure that you don't have some unintended consequences.
So the next thing I ran into is the AJAX cookie problem. And what it looks like is this. The request would be sent by the browser, but it would return 401 unauthorized. Confusingly, if I clicked on that URL there
that was trying to get, it would open up in the browser and would show me that it had returned some JSON. This can be very confusing until you understand that by default jQuery does not send cookies with AJAX requests. And so this prevents the session-based
authentication from working. And it's only within AJAX requests. If you make the same request in the browser, just raw, it'll work because the cookies are being sent. So jQuery has something called withCredentials that we can use to make this work.
It's possible to set withCredentials just on each request, but that can be kind of problematic and there's not really a very clear way to do that on a request-by-request basis in Ember data. So what I've done is set up a AJAX pre-filter that is run every time jQuery tries
to make any AJAX request. And what this does is just immediately prior to the request leaving the browser, the withCredentials option is set to true on the XHR object. It's very simple. But once you do that, it allows things to work.
You see in the console that the request was made and then it came back. And in the network tab, you'll see that it worked and you can inspect the response. So to wrap up, the things that you need to do are understand your requirements and understand how that is going to affect
the decisions that you might make. From there, you just set up authentication so that you can keep track of which user is doing what within the system. Take a few steps to ready things for deployment and then you just enjoy your SOA. Thanks for watching.
Here's my contact info again and I will see you soon.