Class: Rack::OAuth2::Server
- Inherits:
-
Object
- Object
- Rack::OAuth2::Server
- Defined in:
- lib/rack/oauth2/server.rb,
lib/rack/oauth2/models.rb,
lib/rack/oauth2/server/admin.rb,
lib/rack/oauth2/server/utils.rb,
lib/rack/oauth2/models/client.rb,
lib/rack/oauth2/server/errors.rb,
lib/rack/oauth2/server/helper.rb,
lib/rack/oauth2/server/railtie.rb,
lib/rack/oauth2/server/practice.rb,
lib/rack/oauth2/models/access_grant.rb,
lib/rack/oauth2/models/access_token.rb,
lib/rack/oauth2/models/auth_request.rb
Overview
Implements an OAuth 2 Authorization Server, based on tools.ietf.org/html/draft-ietf-oauth-v2-10
Defined Under Namespace
Modules: Utils Classes: AccessDeniedError, AccessGrant, AccessToken, Admin, AuthRequest, Client, ExpiredTokenError, Helper, InvalidClientError, InvalidGrantError, InvalidRequestError, InvalidScopeError, InvalidTokenError, OAuthError, OAuthRequest, Options, Practice, Railtie, RedirectUriMismatchError, UnauthorizedClientError, UnsupportedGrantType, UnsupportedResponseTypeError
Constant Summary collapse
- VERSION =
Same as gem version number.
IO.read(::File.("../../../VERSION", ::File.dirname(__FILE__))).strip
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Options specific for this handle.
Class Method Summary collapse
-
.access_grant(identity, client_id, scope = nil, expires_in = nil) ⇒ String
Creates and returns a new access grant.
- .create_indexes(&block) ⇒ Object
-
.database ⇒ Object
A Mongo::DB object.
-
.get_access_token(token) ⇒ AccessToken
Returns AccessToken from token.
-
.get_auth_request(authorization) ⇒ AuthReqeust
Return AuthRequest from authorization request handle.
-
.get_client(client_id) ⇒ Client
Returns Client from client identifier.
-
.list_access_tokens(identity) ⇒ Array<AccessToken>
Returns all AccessTokens for an identity.
-
.new_instance(klass, fields) ⇒ Object
Create new instance of the klass and populate its attributes.
-
.options ⇒ Object
Global options.
-
.register(args) ⇒ Object
Registers and returns a new Client.
-
.secure_random ⇒ Object
Long, random and hexy.
-
.token_for(identity, client_id, scope = nil, expires_in = nil) ⇒ String
Returns AccessToken for the specified identity, client application and scope.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, options = nil, &authenticator) ⇒ Server
constructor
A new instance of Server.
Constructor Details
#initialize(app, options = nil, &authenticator) ⇒ Server
Returns a new instance of Server.
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/rack/oauth2/server.rb', line 168 def initialize(app, = nil, &authenticator) @app = app @options = || Server. @options.authenticator ||= authenticator @options.access_token_path ||= "/oauth/access_token" @options. ||= "/oauth/authorize" @options. ||= %w{code token} @options.param_authentication ||= false @options.collection_prefix ||= "oauth2" end |
Instance Attribute Details
#options ⇒ Object (readonly)
Options specific for this handle. @see Options
180 181 182 |
# File 'lib/rack/oauth2/server.rb', line 180 def @options end |
Class Method Details
.access_grant(identity, client_id, scope = nil, expires_in = nil) ⇒ String
Creates and returns a new access grant. Actually, returns only the authorization code which you can turn into an access token by making a request to /oauth/access_token.
expires (default to 5 minutes)
86 87 88 89 |
# File 'lib/rack/oauth2/server.rb', line 86 def access_grant(identity, client_id, scope = nil, expires_in = nil) client = get_client(client_id) or fail "No such client" AccessGrant.create(identity, client, scope || client.scope, nil, expires_in).code end |
.create_indexes(&block) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/rack/oauth2/models.rb', line 27 def create_indexes(&block) if block @create_indexes ||= [] @create_indexes << block elsif @create_indexes @create_indexes.each do |block| block.call end @create_indexes = nil end end |
.database ⇒ Object
A Mongo::DB object.
40 41 42 43 44 45 |
# File 'lib/rack/oauth2/models.rb', line 40 def database @database ||= Server..database raise "No database Configured. You must configure it using Server.options.database = Mongo::Connection.new()[db_name]" unless @database raise "You set Server.database to #{Server.database.class}, should be a Mongo::DB object" unless Mongo::DB === @database @database end |
.get_access_token(token) ⇒ AccessToken
Returns AccessToken from token.
95 96 97 |
# File 'lib/rack/oauth2/server.rb', line 95 def get_access_token(token) AccessToken.from_token(token) end |
.get_auth_request(authorization) ⇒ AuthReqeust
Return AuthRequest from authorization request handle.
oauth.authorization)
23 24 25 |
# File 'lib/rack/oauth2/server.rb', line 23 def get_auth_request() AuthRequest.find() end |
.get_client(client_id) ⇒ Client
Returns Client from client identifier.
31 32 33 34 |
# File 'lib/rack/oauth2/server.rb', line 31 def get_client(client_id) return client_id if Client === client_id Client.find(client_id) end |
.list_access_tokens(identity) ⇒ Array<AccessToken>
Returns all AccessTokens for an identity.
118 119 120 |
# File 'lib/rack/oauth2/server.rb', line 118 def list_access_tokens(identity) AccessToken.from_identity(identity) end |
.new_instance(klass, fields) ⇒ Object
Create new instance of the klass and populate its attributes.
12 13 14 15 16 17 18 19 |
# File 'lib/rack/oauth2/models.rb', line 12 def new_instance(klass, fields) return unless fields instance = klass.new fields.each do |name, value| instance.instance_variable_set :"@#{name}", value end instance end |
.options ⇒ Object
Global options. This is what we set during configuration (e.g. Rails’ config/application), and options all handlers inherit by default.
162 163 164 |
# File 'lib/rack/oauth2/server.rb', line 162 def self. @options end |
.register(args) ⇒ Object
Registers and returns a new Client. Can also be used to update existing client registration, by passing identifier (and secret) of existing client record. That way, your setup script can create a new client application and run repeatedly without fail.
existing client registration (in combination wih secret) existing client registration. access (e.g. “My Awesome Application”) name. requests for this client will always redirect back to this URL. (list of names).
67 68 69 70 71 72 73 74 |
# File 'lib/rack/oauth2/server.rb', line 67 def register(args) if args[:id] && args[:secret] && (client = get_client(args[:id])) fail "Client secret does not match" unless client.secret == args[:secret] client.update args else Client.create(args) end end |
.secure_random ⇒ Object
Long, random and hexy.
22 23 24 |
# File 'lib/rack/oauth2/models.rb', line 22 def secure_random OpenSSL::Random.random_bytes(32).unpack("H*")[0] end |
.token_for(identity, client_id, scope = nil, expires_in = nil) ⇒ String
Returns AccessToken for the specified identity, client application and scope. You can use this method to request existing access token, new token generated if one does not already exists.
expires, defaults to never. If zero or nil, token never expires.
109 110 111 112 |
# File 'lib/rack/oauth2/server.rb', line 109 def token_for(identity, client_id, scope = nil, expires_in = nil) client = get_client(client_id) or fail "No such client" AccessToken.get_token_for(identity, client, scope || client.scope, expires_in).token end |
Instance Method Details
#call(env) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/rack/oauth2/server.rb', line 182 def call(env) request = OAuthRequest.new(env) return @app.call(env) if .host && .host != request.host return @app.call(env) if .path && request.path.index(.path) != 0 logger = .logger || env["rack.logger"] # 3. Obtaining End-User Authorization # Flow starts here. return (request, logger) if request.path == . # 4. Obtaining an Access Token return respond_with_access_token(request, logger) if request.path == .access_token_path # 5. Accessing a Protected Resource if request. # 5.1.1. The Authorization Request Header Field token = request.credentials if request.oauth? elsif .param_authentication && !request.GET["oauth_verifier"] # Ignore OAuth 1.0 callbacks # 5.1.2. URI Query Parameter # 5.1.3. Form-Encoded Body Parameter token = request.GET["oauth_token"] || request.POST["oauth_token"] token ||= request.GET['access_token'] || request.POST['access_token'] end if token begin access_token = AccessToken.from_token(token) raise InvalidTokenError if access_token.nil? || access_token.revoked raise ExpiredTokenError if access_token.expires_at && access_token.expires_at <= Time.now.to_i request.env["oauth.access_token"] = token request.env["oauth.identity"] = access_token.identity access_token.access! logger.info "RO2S: Authorized #{access_token.identity}" if logger rescue OAuthError=>error # 5.2. The WWW-Authenticate Response Header Field logger.info "RO2S: HTTP authorization failed #{error.code}" if logger return (request, error) rescue =>ex logger.info "RO2S: HTTP authorization failed #{ex.}" if logger return (request) end # We expect application to use 403 if request has insufficient scope, # and return appropriate WWW-Authenticate header. response = @app.call(env) if response[0] == 403 scope = Utils.normalize_scope(response[1].delete("oauth.no_scope")) challenge = 'OAuth realm="%s", error="insufficient_scope", scope="%s"' % [(.realm || request.host), scope.join(" ")] response[1]["WWW-Authenticate"] = challenge return response else return response end else response = @app.call(env) if response[1] && response[1].delete("oauth.no_access") logger.debug "RO2S: Unauthorized request" if logger # OAuth access required. return (request) elsif response[1] && response[1]["oauth.authorization"] # 3. Obtaining End-User Authorization # Flow ends here. return (response, logger) else return response end end end |