Four Key Reasons to Learn Markdown
Back-End Leveling UpWriting documentation is fun—really, really fun. I know some engineers may disagree with me, but as a technical writer, creating quality documentation that will...
Have you recently used a Twitter, Facebook or Google API? If so, you probably authenticated with OAuth2. Instead of using their own authentication schemes, most new services choose to implement OAuth2, the latest revision of the OAuth protocol. It gives your users a secure way to talk to your service, but more importantly, allows users to safely authorize access to their data from third-party services without giving them their credentials. Let’s build a sample server implementation in Ruby and see how it all works.
Since there are a few moving pieces, take a look at this graph of the typical flow of authentication:
We start off asking the Resource owner to authorize our request, something like the ability to post tweets on their behalf. The user would then accept our request by clicking a link that would redirect them to Twitter and allow them to enter their credentials. Once Twitter confirms the credentials, it redirects the user back to our service including an access token. We can then use this access token to take the action we had previous asked the user about. The advantages here are that the user never gave us their credentials directly, only granted us a specific scope in which to operate, and still has the ability to revoke our access without changing their credentials or affecting other authorized services. Ok that was a lot of explaining. Let’s take a look at some code.
So you want to be able to authorize requests just like Twitter? Let’s go ahead and generate a new rails app and create an OAuthController
. While it’s not the best design, to keep things simple we’re going to do most of the work right in the controller. We can start off by allowing users to register their application with with an application
action. This action will represent the Resource Owner portion of the diagram above.
First we’ll need to create an Application
class to hold on to the client_id
.
class Application < ActiveRecord::Base
has_many :authorizations
before_save :generate_client_id
def generate_client_id
self.client_id = SecureRandom.hex(32)
end
end
Now we can just create one of these in the matching controller action (we’ll add routes for all of these at the end).
def application
respond_with Application.create
end
Ok now we’re on to the important part. We need to find the registered application by client_id
and send the access_token
back to the requesting application. This action will act as the Authorization Server from the diagram above. But remember this isn’t an API call, we have to redirect back.
So let’s create another model to hold the access_token
we generate.
class Authorization < ActiveRecord::Base
belongs_to :application
before_save :generate_access_token
def generate_access_token
self.access_token = SecureRandom.hex(32)
end
end
Now we just need to redirect back to the original url with the access token.
def authorization
client_id = params[:client_id]
request_uri = params[:request_uri]
application = Application.find_by(client_id: client_id)
authorization = application.authorizations.create
access_token = authorization.access_token
redirect_to "#{request_uri}?access_token=#{access_token}"
end
Now for the final touches, wiring up the routes to controller actions.
post '/applications' => 'oauth#application'
get '/authorization' => 'oauth#authorization'
So let’s review how we can use these routes. First we register our application by posting to /applications
. In the response we can find the client_id
parameter used to generate an access_token
. To authorize a user we need to redirect them to /authorization?client_id=…
where the application will allow for its own authorization step and then redirect back to the request_uri
along with the newly generated access_token
.
But what about authorizing requests from a client other than a browser? All we need to do is add another way to generate an access_token
. Typically this means using HTTP Basic Authentication with the credentials of the user. While this doesn’t give us the advantage of keeping our credentials from the client application, at least they are only used once after which we can revoke access independently.
Keep in mind we didn’t cover many pieces of OAuth2 that would be present in a typical production implementation. To implement a full provider we would need more in-depth attributes for applications, knowledge of scope parameters as they related to our application, more robust redirection allowing for multiple query parameters, and better security by validating a client secret and supporting refresh tokens. For a great example check out GitHub’s implementation of OAuth2. Also, there are some great implementations already written like this Rack app and Rails engine.
In the next episode we’ll cover how to use OAuth2 from an iOS app.
Writing documentation is fun—really, really fun. I know some engineers may disagree with me, but as a technical writer, creating quality documentation that will...
Humanity has come a long way in its technological journey. We have reached the cusp of an age in which the concepts we have...
Go 1.18 has finally landed, and with it comes its own flavor of generics. In a previous post, we went over the accepted proposal and dove...