Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
h2. merb-auth-core
MerbAuth is an authentication framework for use with the Merb web framework.
MerbAuth does not try to dictate what you should use as a user model, or how
it should authenticate. Instead it focuses on the logic required to check
that an object passes authentication, and store the keys of authenticated
objects in the session. This is in fact the guiding principle of MerbAuth. The Session is
used as the place for authentication, with a sprinkling of controller helpers.
You can choose to protect a controller action, or a route / group of routes.
This makes sense to talk about an authenticated session. For example, inside
your controller:
session.authenticated?
returns true if the session has been
authenticated. False otherwise # session.authenticate(controller)
authenticates the session based on customizable user defined rules
session.user
returns the currently authenticated user object
session.user= manually sets the currently authenticated user object
session.abandon!
sets the session to unauthenticated, and clears all session data
session.authenticate! authenticates the session against the active strategies
MerbAuth makes use of Merb's exception handling facilities which return correct HTTP status codes when a 200 OK would be inappropriate. To fail a login, or to force a login at any point in your controller code, simply raise an Unauthenticated exception, with an optional message and the user will be presented with login page. The login page is in fact the html view for Extensions#unauthenticated
To protect your controllers, add a simple @before@ filter to your controller.
before :ensure_authenticated
It is possible to use MerbAuth with any object as a user object, provided
that object does not evaluate to false and it can be serialized in an out of the session.
For this reason, merb-auth-core does not try to implement even a simple login
form for you, since it may not meet your requirements.
h3. How Does It Authenticate my arbitrary user?
This is very similar to the BootLoader process in Merbs initialization.
You declare a class that inherits from Merb::Authentication::Strategy and
define an instance method @run!@
class PasswordStrategy < Merb::Authentication::Strategy
def run!
if params[:login] && params[:password]
user_class.authenticate(params[:login], params[:password])
end
end
end
bq. This login strategy uses the @authenticate@ method on the User class to retrieve a user by @login@ and @password@. Remember, you can put as much logic here as you require. The strategy uses an instance variable so the full power of classes are available to your strategy.
The strategy provides access to the current request giving you access to the params hash, session etc.
To pass authentication, simply return a non-nil non-false value from the @run!@ method. Any false or nil value will cause that strategy to fail. Then the next strategy will be tried.
You can add as many strategies as you like and they will be tried one after another until either one is found that works (login), or none of them have passed (failed attempt).
class PasswordLoginBasicAuth < Merb::Authentication::Strategy
def run!
if params[:api_key] && params[:api_token]
Machine.api_authenticate(params[:api_key], params[:api_token])
end
end
end
Now that we have two, they will be executed in the order that they were declared when we call @session.authenticate!(self)@. The first one that returns a value that doesn't evaluate to false, will be considered the winner.
h3. Customizing the user_class
Notice the @user_class@ method in the above strategy examples. This is a convenience method on a strategy to provide you with the user_class to use for this strategy. You can overwrite this method on a per strategy basis to use different user model types. You do not have to use this method and it's only there to keep track of the "default" user class. (if any)
By default the strategy#user_class method will defer to Merb::Authentication#user_class. You can set which is the "default class" that Merb::Authentication will use in the provided strategies by setting it in Merb.root/merb/merb-auth/setup.rb
Merb::Authentication.user_class = Person
This will cascade throughout the default strategies, and your own strategies using the user class that you defined. In this case Person.
There is no default class set for Merb::Authentication.user_class by default
h3. Strategies and Inheritance
Strategies may be inherited multiple times to make the job of combining similar aspects easier.
You can inherit as many levels as you like and at any point you may mark a strategy as abstract
An abstract strategy just means that it will not be run when it comes time to authenticate.
Instead it's good to put common logic in and then inherit from it to keep your strategies DRY.
To mark a class as abstract, use the @abstract!@ class method.
class AbstractStrategy < Merb::Authentication::Strategy
abstract!
end
At any point you can activate a registered strategy. You don't need to register your strategies, you just declare them, but plugin developers make life easier when they do.
To activate a registered strategy:
Merb::Authentication.activate!(:defualt_password_form)
You can easily mix this in with your own strategies. In you Merb.root/merb-auth/strategies.rb
class MyStrategy < Merb::Authentication::Strategy
def run!
#...
end
end
Merb::Authentication.activate!(:default_openid)
class AnotherStrategy < Merb::Authentication::Strategy
def run!
#...
end
end
This will collect them in order of declaration. i.e.: MyStrategy, Merb::Authentication::Strategies::Basic::OpenID, AnotherStrategy
h3. Customizing the order of the strategies
By default, strategies are run in the order they are declared. It's possible to customize the order that the strategies are called.
@Merb::Authentication.default_strategy_order@ will return an array of
the strategy classes in the order that they will be run.
You can customize this by setting the default_strategy_order array
manually.
@Authenticateion.default_strategy_order.order = [Second, First, Fourth]@
It's possible to leave some out, and re-order existing ones. It will error out if you specify one that doesn't exist though.
h3. Authentication based on Routes
With MerbAuth you can protect routes rather than individual actions on a controller. The benefit with doing this is that the request is stopped earlier in the request process. This is a more efficient method of protection than controller based protection.
The downside is that a controllers action is not guaranteed to be protected. For example
authenticate do
match("/one").to(:controller => "one", :action => "index")
end
match("/two").to(:controller => "one", :action => "index")
The /one route is protected, but you can see that both of these routes point to the same controller action. If the One#index method is accessed through the /two route, there is no protection. You can specify which strategies to use as arguments to the authenticate method. The default strategies are used if there is no argument given.
h3. Specifying selected strategies per action
If you need to protect an action regardless of which route leads to it, you can use controller level protection. Use a @before :ensure_authenticated@ filter to protect actions in your controller whenever the are accessed.
It's possible to configure each call to @ensure_authenticated@ with a custom list of strategies to run. These will be run in order and should have an instance method of #run!
class ApiMethods < Application
before :ensure_authenticated, :with => [
Merb::Authenticated::Strategies::Basic::Form,
Merb::Authenticated::Strategies::Basic::BasicAuth,
Merb::Authenticated::Strategies::Basic::OpenID,
],
:only => [:index]
before :machine_only, :only => [:create]
def index
display @stuff
end
def create
stuff = Stuff.create(params[:stuff])
display stuff
end
private
def machine_only
ensure_authentiated Merb::Authenticated::Strategies::Basic::OAuth, Merb::Authenticated::Strategies::Basic::BasicAuth
end
end
You can see in this example that you can specify a list of strategies to use. These will be executed in the order of the array passed in, with the default order ignored completely.
h3. Where should Strategies be defined?
You should store your strategies in
merb
`-- merb-auth
|-- setup.rb
`-- strategies.rb
This is a good place to put everything together so you can see what you're doing at a glance. It is also auto included by merb-auth-core when you're using it.
h3. What Strategies are there?
See merb-auth-more
h3. Storing you user object into the session
You need to tell MerbAuth how to serialize your object into and out of the session. If possible try not to store large or complex data items in the session but just store the objects key.
To configure your user object to go in and out of the session, here's how you could do it.
class Merb::Authentication
# return the value you want stored in the session
def store_user(user)
return nil unless user
user.id
end
# session info is the data you stored in the session previously
def fetch_user(session_info)
User.get(session_info)
end
end
h3. Registering Strategies
Intended for plugin developers as a way to make it easy to use strategies there is the possibility to register a strategy without loading it.
Authentication.register(:my_strategy, "/absolute/path/to/strategy.rb")
This then allows developers to use
Authentication.activate!(:my_strategy)
h3. Providing feedback to users (Error Messages)
There's at least 4 ways to provide feedback to users for failed logins.
Overwrite Merb::Authentication#error_message The return of this method is the default message that is passed to the Unauthenticated exception. Overwrite this to provide a very basic catch all message.
Provide a default message when you declare your before filter.
before :ensure_authenticated, :with => [Openid, :message => "Could not log you in with open ID"]
# OR
before :ensure_authentication, :with => {:message => "Sorry Buddy... You Lose"}
When you pass a message, it will replace the Merb::Authentication#error_message default for this action
Use an after filter for your login action. This can be used to set your messaging system. For example:
after :set_login_message, :only => [:create]
private
def set_login_message
if session.authenticated?
flash[:message] = "Welcome"
else
flash[:error] = "Bad.. You Fail"
end
end
Use the authentications error messaging inside your strategies to set error messages there. You can add to these errors just like adding to DataMappers validation errors.
session.authentication.errors.add("Label", "You Fail")
Add as many as you like, ask @session.authentication.errors.on(:label)@ to get specific errors etc Really... They're just like the DataMapper validation errors. The bonus of using this system is that you can add messages inside your Strategies, and then in your views you can do this:
<%= error_messages_for sessions.authentication %>
h3. Additional checks / actions to perform after the user is found
Sometimes you may need to perform additional operations on the user object after you have found a valid user in the strategy. There is a hook method Merb::Authentication.after_authentication which is designed for this.
Here's an example of checking that a user object is active after it's been found:
Merb::Authentication.after_authentication do |user, request, params| user.active? ? user : nil end
Pass the user model on if everything is still ok. Return nil if you decide in the after_authentication hook that the user should in fact not be allowed to be authenticated.
By default this plugin doesn't actually authenticate anything ;) It's up to you to get your model going, and add an authentication strategy.
To logout use @session.abandon!@ and to force a login at any time use @raise Unauthenticated, "You Aren't Cool Enough"@
h3. Contributors
FAQs
Unknown package
We found that merb-auth-core demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.