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/models/issuer.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, Issuer, 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.
-
.get_issuer(identifier) ⇒ Issuer
Returns an Issuer from it’s 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.
-
.register_issuer(args) ⇒ Object
Registers and returns a new Issuer.
-
.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.
217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/rack/oauth2/server.rb', line 217 def initialize(app, = nil, &authenticator) @app = app @options = || Server. @options.authenticator ||= authenticator @options.assertion_handler ||= {} @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
230 231 232 |
# File 'lib/rack/oauth2/server.rb', line 230 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)
87 88 89 90 |
# File 'lib/rack/oauth2/server.rb', line 87 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.
96 97 98 |
# File 'lib/rack/oauth2/server.rb', line 96 def get_access_token(token) AccessToken.from_token(token) end |
.get_auth_request(authorization) ⇒ AuthReqeust
Return AuthRequest from authorization request handle.
oauth.authorization)
24 25 26 |
# File 'lib/rack/oauth2/server.rb', line 24 def get_auth_request() AuthRequest.find() end |
.get_client(client_id) ⇒ Client
Returns Client from client identifier.
32 33 34 35 |
# File 'lib/rack/oauth2/server.rb', line 32 def get_client(client_id) return client_id if Client === client_id Client.find(client_id) end |
.get_issuer(identifier) ⇒ Issuer
Returns an Issuer from it’s identifier.
153 154 155 |
# File 'lib/rack/oauth2/server.rb', line 153 def get_issuer(identifier) Issuer.from_identifier(identifier) end |
.list_access_tokens(identity) ⇒ Array<AccessToken>
Returns all AccessTokens for an identity.
119 120 121 |
# File 'lib/rack/oauth2/server.rb', line 119 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.
211 212 213 |
# File 'lib/rack/oauth2/server.rb', line 211 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).
68 69 70 71 72 73 74 75 |
# File 'lib/rack/oauth2/server.rb', line 68 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 |
.register_issuer(args) ⇒ Object
Registers and returns a new Issuer. Can also be used to update existing Issuer, by passing the identifier of an existing Issuer record. That way, your setup script can create a new client application and run repeatedly without fail.
an existing Issuer
141 142 143 144 145 146 147 |
# File 'lib/rack/oauth2/server.rb', line 141 def register_issuer(args) if args[:identifier] && (issuer = get_issuer(args[:identifier])) issuer.update(args) else Issuer.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.
110 111 112 113 |
# File 'lib/rack/oauth2/server.rb', line 110 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
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/rack/oauth2/server.rb', line 232 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 |