Tony Schneider

  • Archive
  • RSS

Nested Routing w/ a parameterized scope

The Rails router is awesome. But every once in a while I come across something I want to do and it’s not immediately obvious. In this particular case I wanted to have a simple nested resource with a scope.

i.e

/foos/:foo_id/:scope/bars/:id

Sounds easy enough, right?

Well, here was my first attempt:

resources :foos do
  member do
    scope ":scope" do
      resources :bars
    end
  end
end

But, to my surprise this generates the following:

/foos/:id/:scope/bars/:id

Oops! That’s no good. In your controller, you’ll only get one of those :id parameters. In fact, I think it might be a bug. Hopefully if I have a few cycles I can try and get a fix in. At the very least a test exposing the observed behavior to see if this is intended.

Anyway, as a work around, I was able to do the following after digging through the source.

resources :foos do
  resources :bars, path: ":scope/children"
end

I wasn’t aware of the path option to resources, and I certainly didn’t know you could make the path parameterized. I hope to improve the docs on this a bit after work.

***note: In production, it’s probably a good idea to add a custom constraint to limit the allowed parameterized scopes - Especially if you’re using that parameter as… I don’t know… a scope.

    • #ruby
    • #rails
    • #routing
    • #scope
    • #resources
  • 6 months ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
Woohoo! I got a rails commit!
Pop-upView Separately

Woohoo! I got a rails commit!

    • #rails
    • #yay!
  • 11 months ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

Rails HTTP status to symbol mapping

    • #rails
    • #http
    • #ruby
  • 1 year ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

OAuth, OAuth2 and Ruby

Recently, some colleagues and I have been working on a client project that involves several different internal web services. Along with the usual user authentication, we needed a way to authenticate and verify API requests across these services.

Let’s start with user authentication. Enter OAuth2…

OAuth2

If you aren’t familiar with the OAuth2 protocol, I’m sure you’ve at least used it as a client. You click the “login-using-some-3rd-party”, get redirected, enter your credentials, get redirected back. Badda boom, badda bing, done - you’re authenticated. This works great for that three-legged exchange of resource owned credentials discussed at length in section 4.1 in the RFC. There are a ton of resources for this. Especially in the ruby/rails space. Some excellent ones to check out are the following:

  • devise_oauth2_providable (github)
  • omniauth (github)

The devise_oauth2_providable is a rails engine that makes creating a standard OAuth2 provider insanely easy. At the time of this post, it is actively maintained. In fact, when we came across a bug during development, it wasn’t more than an hour later and someone had provided a fix, pulled it in, and cut a new version.

Omniauth is a wonderful little gem that provides an excellent abstraction for any type of client authentication. It has templates that provide a simple DSL for the most popular authentication schemes.

This workflow is excellent when you have a service that wishes to authenticate using a third party (like Facebook or Google). However, since the we owned both the OAuth2 provider and the OAuth2 client, it seems pretty silly to redirect to our Authentication server, enter credentials, and redirect back our client app. Fortunately, the OAuth2 specifies a protocol for this use case as well in Section 4.3 of the RFC.

As a fan of the omniauth abstraction, I looked into the OAuth2 abstract strategy for easily defining OAuth2 client strategies. Unfortunately it is designed for use with the Authorization code grant type. To solve this, a co-worker and I made a similar omniauth abstract strategy for providing the functionality defined in section 4.3 (should be open source shortly). Having used devise_oauth2_providable for the OAuth2 provider, it just worked.

Now, for the final piece of the puzzle, authenticating API requests. Again, OAuth2 has a flow for this use case. It’s specified in the Client Credentials grant type in section 4.4. However, we noticed a problem. The OAuth2 specification had been edited a week prior. And on top of that, section 4.4 relies only on Basic Auth. I’m sure this has its use cases, but after some research there appears to be a lot of discussion on whether or not this is a sufficient solution.

We certainly wanted something more secure than Basic Auth. Enter OAuth 1.0…

OAuth 1.0

OAuth 1.0 solves the same problems that OAuth 2 aims to solve, but in a different (arguably more secure) way. It also supports workflows analogous to sections 4.1, 4.3, and 4.4 of OAuth2. So, given the current state of the OAuth2 RFC, if you need the functionality described in the client credentials grant type of OAuth2, and basic auth doesn’t provide enough security, you’re probably better off using OAuth 1.0.

If you’re using Ruby, you might be tempted to use the oauth gem. I would highly recommend not doing this given the state of the gem. The github network graph seems to imply a pretty heavily divergent state. Having found at least one bug, and a serious lack of tests and documentation, I hope you’ll learn from my mistake and look elsewhere.

Fortunately, there are some pretty amazing options that I wish I would have found earlier. Here’s a quick recap:

  • simple_oauth (github) - It is just that. It signs and verifies OAuth requests. This gem has tests, documentation, and is well maintained.
  • faraday_middleware (github) - This is a bit of Rack middleware that works alongside the excellent Faraday gem. It comes with a couple middlewares for tampering with outgoing requests, two of which include OAuth and OAuth2.

So, if you’re integrating the oauth or oauth2 protocols into one of your services, hopefully you’ll find this bit of first hand experience useful.

Other useful/helper links:

  • http://hueniverse.com/2010/09/oauth-2-0-without-signatures-is-bad-for-the-web/
  • http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-00
    • #OAuth 1.0
    • #OAuth 2.0
    • #OAuth
    • #Rails
    • #Ruby
    • #oauth-ruby
    • #simple_oauth
    • #faraday
    • #faraday_middleware
  • 1 year ago
  • 1
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

ActiveRecord & ActiveRecord::Observer Callbacks

    • #ruby
    • #rails
    • #rails 3.1
  • 1 year ago
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

Around Aliasing

I’m making my way through Paolo Perrotta’s Metaprogramming Ruby book and I stumbled upon this nugget of Ruby meta-magic..

class Fixnum
  alias :new_plus :+
  
  def +(num)
    old_plus(old_plus(1))
  end
end

1 + 1 => 3

At first glance this may appear to be merely a technique to show off the flexibility of Ruby, but as it turns out, it is quite useful in day-to-day programming. This technique is known as an “Around Alias” and can be seen in many popular Ruby libraries. One in particular being Rails, which uses this technique in the mind numbingly cool #alias_method_chain method. Go check out Rails source if you’d like to read up on #alias_method_chain.

Here’s an immediately useful and simple application of Around Aliasing adapted from an example given in the text:

alias :safe_method_that_calls_api :method_that_calls_api

def method_that_calls_api
  start_time = Time.now
  result = safe_method_that_calls_api
  time_taken = Time.now - start_time
    
  if time_taken > 2
    puts "method_that_calls_api() took #{time_taken} seconds."
  end
  result
rescue
  puts "method_that_calls_api() failed."
  []
end
    • #metaprogramming
    • #ruby
    • #around alias
    • #rails
  • 1 year ago
  • 3
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

About

Avatar Hello there,

I'm a recent graduate of The Ohio State University. While attending OSU, I studied Computer Science & Engineering and minored in Studio Art.

I'm currently a software developer working for Neo. I'm an avid music listener, movie watcher, concert goer, and traveler.

You've stumbled upon a bag of my favorite links, thoughts, lessons, and opinions. I hope you enjoy.

Pages

  • Year End Lists

Me, Elsewhere

  • tonywok on Forrst
  • @tonywok on Twitter
  • tsnydermtg on Last.fm
  • My Skype Info
  • tonywok on github

Twitter

loading tweets…

  • RSS
  • Random
  • Archive
  • Mobile
Effector Theme by Pixel Union