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
Class Method Summary collapse
-
.access_grant(identity, client_id, scope = nil, expires = nil) ⇒ String
Creates and returns a new access grant.
-
.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.
-
.register(args) ⇒ Object
Registers and returns a new Client.
-
.secure_random ⇒ Object
Long, random and hexy.
-
.token_for(identity, client_id, scope = nil) ⇒ String
Returns AccessToken for the specified identity, client application and scope.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, options = Options.new, &authenticator) ⇒ Server
constructor
A new instance of Server.
Constructor Details
#initialize(app, options = Options.new, &authenticator) ⇒ Server
Returns a new instance of Server.
155 156 157 158 159 160 161 162 163 |
# File 'lib/rack/oauth2/server.rb', line 155 def initialize(app, = Options.new, &authenticator) @app = app @options = @options.authenticator ||= authenticator @options.access_token_path ||= "/oauth/access_token" @options. ||= "/oauth/authorize" @options. ||= %w{code token} @options.param_authentication ||= false end |
Instance Attribute Details
#options ⇒ Object (readonly)
166 167 168 |
# File 'lib/rack/oauth2/server.rb', line 166 def @options end |
Class Method Details
.access_grant(identity, client_id, scope = nil, expires = 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 = nil) client = get_client(client_id) or fail "No such client" AccessGrant.create(identity, client, scope || client.scope, nil, expires).code 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)
23 24 25 |
# File 'lib/rack/oauth2/server.rb', line 23 def get_auth_request() AuthRequest.find_by_code() 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) p client_id Client.find_by_code(client_id) end |
.list_access_tokens(identity) ⇒ Array<AccessToken>
Returns all AccessTokens for an identity.
117 118 119 |
# File 'lib/rack/oauth2/server.rb', line 117 def list_access_tokens(identity) AccessToken.from_identity(identity) 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 |
.secure_random ⇒ Object
Long, random and hexy.
15 16 17 |
# File 'lib/rack/oauth2/models.rb', line 15 def self.secure_random OpenSSL::Random.random_bytes(32).unpack("H*")[0] end |
.token_for(identity, client_id, scope = 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.
108 109 110 111 |
# File 'lib/rack/oauth2/server.rb', line 108 def token_for(identity, client_id, scope = nil) client = get_client(client_id) or fail "No such client" AccessToken.get_token_for(identity, client, scope || client.scope).token end |
Instance Method Details
#call(env) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 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 |
# File 'lib/rack/oauth2/server.rb', line 168 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 begin 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]["oauth.no_scope"]) challenge = 'OAuth realm="%s", error="insufficient_scope", scope="%s"' % [(.realm || request.host), scope] 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 end |