Giter VIP home page Giter VIP logo

fraunhofer-aisec / omejdn-server Goto Github PK

View Code? Open in Web Editor NEW
12.0 4.0 19.0 488 KB

Omejdn is an OAuth2/OpenID connect server for IoT devices which use their private keys to request OAuth2 access tokens in order to access protected resources and websites or apps which retrieve user attributes.

License: Apache License 2.0

Dockerfile 0.14% Ruby 95.43% CSS 1.15% Haml 3.09% Shell 0.19%
oauth2-server oauth2 daps openid-connect bavaria

omejdn-server's Introduction

Omejdn (Bavarian for "Log in")

build-server GitHub release (latest SemVer)

Omejdn

Omejdn is a minimal but extensible OAuth 2.0/OpenID connect server used for ...

  1. IoT devices which use their private keys to request OAuth2 access tokens in order to access protected resources
  2. Websites or apps which retrieve user attributes

It is used as the Dynamic Attribute Provisioning Service (DAPS) prototype of the Industrial Data Space.

Some of Omejdn's core features include:

  • Database-free easy-to-read configuration files
  • Integration of existing LDAP directory services
  • Fully configurable through the Admin API Plugin
  • A User Selfservice API Plugin
  • Standard Compliance (see below)

IMPORTANT: Omejdn is meant to be a research sandbox in which we can (re)implement standard protocols and potentially extend and modify functionality under the hood to support research projects. Use at your own risk! At a minimum, take a look at the documentation for production setups.


Quickstart

The main configuration file is config/omejdn.yml. It will be generated when you first run Omejdn. The default values result in a plain OAuth 2.0 server with no OpenID support and no way to add users via an API, served at http://localhost:4567

Depending on your use case, you might want to at least configure the following options:

  • issuer: https://example.org defines Omejdn's Issuer Identifier. It is used for finding Omejdn's endpoints.
  • front_url: https://example.org/auth should point to where Omejdn is mounted. Defaults to issuer above. If the two values differ or have a path segment, make sure to relay the well-known endpoints for the issuer according to the documentation.
  • openid: true enables OpenID functionality
  • accept_audience should include the issuer identifier and $front_url/token. Delete this config option to generate a default one for your setup.

To start Omejdn, simply execute

$ bundle config set --local with omejdn
$ bundle config set --local without plugins development # Include these for more complex setups and development
$ bundle install
$ ruby omejdn.rb

You may now add clients and users as decribed below, and request access tokens for them. The token endpoint is /token and the authorization endpoint is /authorize, as advertised at /.well-known/oauth-authorization-server.

For testing purposes, a script for creating JWT Bearer Tokens for client authentication is located at scripts/create_test_token.rb.

Configuration

This section provides but a very brief overview of the possible configuration options. When in doubt, take a look at the documentation in /docs. By default, all configuration options are specified in files under /config and /keys. Omejdn's Plugin system however allows them to be located almost anywhere (including databases, remote locations, ...).

Signing keys

The server public/private key pair used to sign tokens is located at keys/omejdn/omejdn.key in PEM format. This file will be auto-generated, if it does not exist. If you would like to use your own key, simply replace this file. You may place other keys and certificates in this folder to have the keys be advertised via the JWKS endpoint (e.g. for key rollover).

Clients

Clients are configured in config/clients.yml using the client registration parameters. A minimal public client needs to have

  • a unique client_id
  • a token_endpoint_auth_method with a value of none
  • at least one value listed under redirect_uris
  • at least one value listed under scope

Users

Users are configured in config/users.yml. Each user has at least a username, password, and an empty array of attributes, which are (in their simplest form) key-value pairs describing information about the user. For instance:

- key: given_name
  value: Alice

For more complex setups take a look at the documentation.

Scopes and Attributes

A client can request any subset of scopes in his scopes, configurable in the client configuration file. If you define a set of attributes for a scope in config/scope_mapping.yml, the userinfo endpoint response will also include this attribute for OpenID requests.

(Note: You can also add those attributes to the Access- and ID Tokens. Have a look at the attributes claim mapper plugin.)

Scopes of the form k:v are granted if the resource owner (the user in authorization code flows) contains an attribute with key k and value v. Other scopes are granted if the resource owner contains at least one attribute which the scope under consideration maps to. See the documentation for details.

In config/scope_description.yml you can configure a short description string which is displayed to the user in an OpenID Connect flow upon requesting authorization.

There are some special predefined scopes you may want to use:

  • openid, profile, email: These scopes are defined by OpenID.
  • omejdn:*: These scopes are reserved for use with Omejdn and its APIs. Values include:
    • omejdn:read and omejdn:write for access to the User Selfservice API Plugin.
    • omejdn:admin for access to the Omejdn Admin API Plugin.

Plugins

Omejdn's functionality can be customized through the use of plugins. For more information please take a look at the documentation.

Using the Omejdn Docker Image

Omejdn comes with its own Docker images, which you can either grab from ghcr.io, or build yourself like so:

$ docker build . -t my-omejdn-server
$ docker run -d  --name=omejdn -p 4567:4567 \
              -v $PWD/config:/opt/config \
              -v $PWD/keys:/opt/keys my-omejdn-server

Most of Omejdn's core features (excluding plugins) can be configured via environment variables, by upper-casing the config option and prepending OMEJDN_. For instance, setting OMEJDN_ISSUER will overwrite the issuer configuration option.

To add an admin user, set OMEJDN_ADMIN to username:password.

Supported Standards

This server mostly implements the following standards (potentially via plugins):

NOTE: Omejdn only implements two grant types:

  • client_credentials for RFC7523.
  • authorization_code for OpenID Connect.

In particular, it does not implement the JWT bearer authorization grant or the Implicit Grant.

The only OpenID Connect authorization flow supported is the authorization code flow (with or without PKCE). As specified in the OAuth2 Security Best Current Practice Document, these are the only grant types we will likely support for OAuth2.0 and OpenID Connect.

Directory Structure

Omejdn uses the following directory structure:

\_ omejdn.rb                 (Omejdn Source code)
\_ lib/                      (Additional Source code)
\_ plugins/                  (Plugin Source code)
\_ config/
    \_ omejdn.yml            (The main configuration file)
    \_ clients.yml           (Client configuration file)
    \_ webfinger.yml         (Webfinger configuration)
    \_ oauth_providers.yml   (To configure external OpenID Providers)
    \_ scope_description.yml (Human-readable strings for Scopes)
    \_ scope_mapping.yml     (Mapping Scopes to Attributes)
\_ keys/
    \_ omejdn/               (Keys and Certificates to be JWKS-advertised)
        \_ omejdn.key        (The OAuth2 server private key)
    \_ clients/              (The public key certificates for clients)
\_ views/                    (Web-Pages)
\_ public/                   (Additional frontend resources (CSS+Images))
\_ docs/                     (Documentation)
\_ tests/
    \_ test_*.rb             (Unit and E2E tests for Omejdn)
    \_ test_resources/       (Test vectors)
\_ scripts/                  (Convenience Scripts)

omejdn-server's People

Contributors

bellebaum avatar dependabot[bot] avatar erickquintanar avatar milux avatar oxisto avatar schanzen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

omejdn-server's Issues

Outputs are cached instead of written to stdout on Docker

When trying to run Omejdn as a Docker container, outputs of statements like

puts "TEST"

do not appear in the logs instantly, when queried using docker logs or when running Docker in the foreground.
They eventually appear after the container has been stopped, suggesting some sort of caching mechanism.

Problems with Ruby and Docker of this sort are known and a few possible workarounds are documented here.

Invalid request: Content longer than specified

omejdn-version: 1.7.1

Hi, we're using omejdn-server in out test environment with some EDC instances.
Sometimes (like 2 calls out of 30) we get this error on the server:

2022-10-10 08:47:56 +0000 Invalid request: Content longer than specified
  /usr/local/bundle/gems/thin-1.8.1/lib/thin/request.rb:79:in `parse'
  /usr/local/bundle/gems/thin-1.8.1/lib/thin/connection.rb:39:in `receive_data'
  /usr/local/bundle/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run_machine'
  /usr/local/bundle/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run'
  /usr/local/bundle/gems/thin-1.8.1/lib/thin/backends/base.rb:75:in `start'
  /usr/local/bundle/gems/thin-1.8.1/lib/thin/server.rb:162:in `start'
  /usr/local/bundle/gems/thin-1.8.1/lib/rack/handler/thin.rb:22:in `run'
  /usr/local/bundle/gems/sinatra-2.1.0/lib/sinatra/base.rb:1565:in `start_server'
  /usr/local/bundle/gems/sinatra-2.1.0/lib/sinatra/base.rb:1499:in `run!'
  /usr/local/bundle/gems/sinatra-2.1.0/lib/sinatra/main.rb:45:in `block in <module:Sinatra>' 

that results in a timeout on the EDC side.
What could be the issue?

full deployment configuration

  clients.yml: |-
    ---
    - client_id: the-client-id
      name: omejdn admin ui
      client_secret: the-client-secret
      token_endpoint_auth_method: client_secret_post
      attributes:
      - key: omejdn
        value: admin
      redirect_uris:
      - https://example.org/callback01
      - https://example.org/callback02
      - https://oauth.pstmn.io/v1/callback
      - "/"
      scope:
      - omejdn:admin
      grant_types:
      - client_credentials
  omejdn.yml: |-
    ---
    issuer: https://daps.dev.demo.mydomain.com
    front_url: https://daps.dev.demo.mydomain.com
    bind_to: 0.0.0.0:4567
    environment: development
    openid: false
    default_audience: idsc:IDS_CONNECTORS_ALL
    accept_audience:
    - https://daps.dev.demo.mydomain.com/
    - https://daps.dev.demo.mydomain.com/token
    - idsc:IDS_CONNECTORS_ALL
    access_token:
     expiration: 3600
     algorithm: RS256
    id_token:
     expiration: 3600
     algorithm: RS256
    user_backend:
    - yaml
  plugins.yml: |-
    ---
    plugins:
      admin_api:
      token_user_attributes:
        skip_access_token: false
        skip_id_token: false
  scope_mapping.yml: |-
    ---
    plugins:
    omejdn:read:
    - omejdn
    omejdn:write:
    - omejdn
    omejdn:admin:
    - omejdn
    profile:
    - name
    - family_name
    - given_name
    - middle_name
    - nickname
    - preferred_username
    - profile
    - picture
    - website
    - gender
    - birthdate
    - zoneinfo
    - locale
    - updated_at
    email:
    - email
    - email_verified
    address:
    - formatted
    - street_address
    - locality
    - region
    - postal_code
    - country
    phone:
    - phone_number
    - phone_number_verified
    idsc:IDS_CONNECTOR_ATTRIBUTES_ALL:
    - "@type"
    - "@context"
    - "securityProfile"
    - "referringConnector"

API and admin access scope handling should be improved

Currently, the scopes omejdn:api and omejdn:admin can be requested and if the attributes with such keys are configured the respective access tokens can be used to access the (admin) API.

A better approach would be to have scopes such as:

  • omejdn:read
  • omejdn:write
  • omejdn:admin

Those scopes then map to an attribute omejdn which can have the values read, write, admin
.

Adding edit rights to specific attributes

Currently, there is no input sanitization when issuing PUT calls to /api/v1/user.
This allows a user (among others) to

  • update their profile, but also to
  • edit their API access rights by submitting an attribute "omejdn" with a value of e.g. "admin",

This begs the question of which attributes should be editable by a user. Maybe we should add a blacklist to some config file with attributes that no user should be able to manage themselves. We probably also want to set restrictions on values that can be set at all (e.g. all claims defined in the scope mapping?)

Secured Authorization Requests

Currently, request parameters for the /authorize endpoint are routed via the user agent, to be included in an HTTP GET request to Omejdn.

Several mitigations to this problem exist:

  • The OpenID request and request_uri parameters, allowing for signed request parameters (link)
    • OAuth has something similar (link)
  • Pushed Authorization Requests, allowing clients to preregister most request parameters (link)

Besides the mentioned benefits, implementing these also allows to encode authorization requests as e.g. "tiny" QR codes, which may be useful to building hands-on demonstrators

Implement the OpenID auth_time claims and max_age parameters

If Omejdn wants to be OpenID compliant, https://openid.net/specs/openid-connect-core-1_0.html#ServerMTI provides a non-exhaustive list of features that must be implemented.

Among others, these are currently missing:

  • Authentication Time
  • Maximum Authentication Age

We probably want to implement them and keep track of the last time we authenticated a user. When doing so, we could also react to the prompt parameter requesting an explicit relogin.

Simpler Certificate File Names

Currently, Omejdn places and expects the certificate file of any client to be placed here:

def certificate_file
  "keys/#{Base64.urlsafe_encode64(@client_id)}.cert"
end

The idea was to

  1. have a static place for each client's certificate, so that Omejdn can accept (via its API) new ones without having to expose the file system layout.
  2. have the character set for the filename be something predictable.

The Base64url-encoding shown above has however proven very unintuitive in practice. A simpler way would be:

def certificate_file
  "keys/#{@client_id}.cert"
end

Some notes:

  • client_id should be *(%x20-7E) according to RFC 6749, i.e. ANY string of arbitrary printable ASCII characters.
    • Fun fact: Omejdn never checks...
  • Some characters have caused problems in the past, such as =
  • Any mapping must be injective (avoid collisions)

Questions:

  • Which characters are potentially causing problems in common use cases?
  • How do we deal with them in a standardized way that is intuitive for most users?

The ```resource_owner.attributes``` field used by ```filter_scopes``` is not a ```Hash```

The current filter_scopes function execution results in a HTTP 500 when the /consent endpoint is called.
I am not sure if that is caused by a configuration error on my side though.

def filter_scopes(resource_owner, client, scopes)
  scope_mapping = Config.read_config CONFIG_SECTION_SCOPE_MAPPING, {}
  ((scopes || []) & [*client.metadata['scope']]).select do |s|
    if s == 'openid'
      true
    elsif s.include? ':'
      key, value = s.split(':', 2)
      av = resource_owner.attributes[key] # <--  resource_owner.attributes.class is not a Hash; indexing with a String
      av = { 'value' => av } unless av.instance_of?(Hash)
      av && av['value'] == value
    else
      (scope_mapping[s] || []).any? { |claim| resource_owner.attributes[claim] }
    end
  end
end

users.yml:

---
- username: admin
  attributes:
  - key: omejdn
    value: admin
  password: "$2a$12$At/un58ws8tY7VCAyvC0zulZIwNRC.rHvUGmpOc58yhMQawBbYrvG" # password
  backend: yaml

clients.yml:

---
- client_id: adminUI
  client_name: Omejdn Admin UI
  client_uri: http://localhost:4200
  logo_uri: http://localhost:4200/assets/img/fhg.jpg
  grant_types:
    - authorization_code
  software_id: Omejdn Admin UI
  software_version: 0.0.0
  token_endpoint_auth_method: none
  redirect_uris: http://localhost:4200
  post_logout_redirect_uris: http://localhost:4200
  scope:
    - openid
    - omejdn:write
    - omejdn:admin
    - omejdn:read
  attributes: []

My proposed change Fork:

     elsif s.include? ':'
       key, value = s.split(':', 2)
-      av = resource_owner.attributes[key]
+      av = resource_owner.attributes.find { |hash| hash['key'] == key }
       av = { 'value' => av } unless av.instance_of?(Hash)
       av && av['value'] == value

DAPS capability of holding one attribute

omejdn-server/omejdn.rb

Lines 178 to 190 in c767a7a

def filter_scopes(resource_owner, scopes)
scope_mapping = Config.scope_mapping_config
scopes.select do |s|
if s == 'openid'
true
elsif s.include? ':'
key, value = s.split(':', 2)
resource_owner.claim?(key, value)
else
(scope_mapping[s] || []).any? { |claim| resource_owner.claim?(claim) }
end
end
end

We heard that the DAPS has the capability to contain only one claim, we would like to ask if

key, value = s.split(':', 2)

is the reason for this capability.

If yes it would be interesting why it is implemented in the way to hold only one attribute and not multiple ones?

OAuth2 resource indication

We may want to have RFC8707 and accordingly allow to modify the "aud" claim in our access token JWT.
This likely requires a client/user configuration which allows us to white/blacklist resources.

Request-Provided Claim Values Support

This is a feature suggestion for support of claims that are copied from the user's request.
The main idea behind this feature is to bind specific, (server side) preconfigured dynamic attributes into issued tokens, whereas the values of these attributes are defined upon request by the client.

Typical use cases include:

  • fingerprints of short-lived TLS certificates used for communication among clients
  • ephemeral or short-lived public keys that are to be bound to the client identity

PR to follow.

Wrong filename for File.read

If a yaml is used instead of a sqlite db, keys are stored in the keys folder. In this case the cliet.rb should read as follows:

 if ccnf['certfile']
        filename = "keys/"+ccnf['certfile']
        begin
          client.certificate = OpenSSL::X509::Certificate.new File.read filename
          needs_save = true
        rescue StandardError => e
          p "Unable to load key ``#{filename}'': #{e}"
        end
      end
      client
    end

Logout URL formatting issue

Omejdn should append the optional state parameter to the post logout redirect URI as a query parameter, not by simple concatenation

Misleading documentation

There are two ways to install the DAPS, one with the oficial git at https://github.com/International-Data-Spaces-Association/omejdn-daps where the installation is made with bundle and the other at https://github.com/Fraunhofer-AISEC/omejdn-server that is made with docker.

In the second link, it states how to install it using docker, yet in the first page, this option is no written. The two methods are not well connected and it leads to misinterpretation. The documentation, and the part on how to do it with dockers, should be included in the oficial documentation, and there steps to reach that point clearly stated and well separated.

It should appear all the steps that are neccesary to reach the point of the installation with docker

Certificate Bound Access Tokens

Omejdn is occasionally used in a way that allows to bind transport certificates to the issued access tokens. This can be quite useful if access tokens are not to be reused by resource servers and other parties receiving such tokens.

One example usage: IDS-G defines transportCertsSha256

As Omejdn does not support detecting transport certificates (nor requests them), this parameter is usually configured though the attributes of clients or users, and subsequently included in the issued access tokens. This is quite inflexible and requires updates either via the API or manually.

Alternatives:

  • RFC 8705 provides a direct way to hint at the client's certificate used for TLS in the cnf.x5t#S256 claim of the access token. TLS Client authentication can also be made optional by providing specialized endpoints requiring it.
    • This is quite elegant but does require direct access to the TLS certificates. This may be done using NginX's features to convey them in a header, but this would possibly restrict the setups which may involve Omejdn.
    • We could also just do TLS inside Omejdn.
  • DPoP sends a Proof of Posession as an HTTP Header.
    • Easier to work with for Omejdn, but does require clients to have access to their keys at an application layer.

JWKS endpoint as a high risk resource of the entire dataspace

Hi Team,

I've been doing some risk analysis regarding DAPS / omejdn-server and came up with 1 potential risk that might be worth mentioning in
https://github.com/Fraunhofer-AISEC/omejdn-server/blob/master/docs/Setup/Production.md

In general I'm arguing that the jwks.json endpoint is the most critical resource in the entire Dataspace. Why? Because in case someone can add their public key to it, all connectors would trust tokens created by this entity.

Right now, I did not find a way to do this, but I would say there is at least a risk. I think it could happen in combination with another potential issue.

To not make it too abstract, a potential scenario could be the following:
An attacker smuggles in 1 line of code as part of a bigger change:

configure do
  # Load Plugins
  PluginLoader.initialize

  config = Config.setup
  set :environment, (proc { Config.base_config['environment'].to_sym })
  enable :dump_errors, :raise_errors, :quiet
  disable :show_exceptions
  bind_ip, bind_port = config['bind_to'].split(':')
  set :bind, bind_ip
  set :port, bind_port if bind_port
  enable :sessions
  set :sessions, secure: (config['front_url'].start_with? 'https://')
  set :session_store, Rack::Session::Pool
  # ----> following line enables possible attack! <---
  set :protection, :except => :path_traversal
end

This disables some very important path param checks. With this, and access to the API, an attacker could do:

POST "/api/v1/config/clients/%2E%2E%2Fomejdn%2Fevil/keys"

In such a case, the path param will be resolved to ../omejdn/evil and the evil certificate would be stored in ../omejdn/evil.cert instead of the clients directory! And consequently being loaded into the JWKS endpoint.

Flow

daps_jwks_risk

Recommendation

Therefore, I would recommend for production environments to clearly separate the JWKS endpoint - which is rather static content anyway - from the rest of the rather dynamic DAPS environment. I think this lowers the risk of such an attack dramatically.

In some cases, I could even imagine, to independently monitor the JWKS content.

Any thoughts on this?


Matthias Binzer
Robert Bosch GmbH

Sanitize scopes in Session

If a client asks for authorization twice, and for a subset of the first request's scopes when asking for the second time,
Omejdn no longer asks the user for consent (Yes, refresh tokens and revocation would be wiser). But it also grants all scopes from the first request instead of the subset requested with the second request.

Cache-Control Header missing

RFC 6749 states:

The authorization server MUST include the HTTP "Cache-Control"
response header field [RFC2616] with a value of "no-store" in any
response containing tokens, credentials, or other sensitive
information, as well as the "Pragma" response header field [RFC2616]
with a value of "no-cache".

Currently Omejdn is not compliant

Features and Specification

With the last commit 3126324 a lot of things changed. I understand, that no new version was released, but could you nevertheless elaborate more on following points?

  • Are there breaking changes for service consumers (Connectors)?
  • Which new features are to be expected with the commit and further developments?
  • What is planned with "Beginnings of Admin API v2" and what is the purpose?
  • I heard that a DAPSv3 Spec is planned, which might adjust routes to /.well-known/jwks.json
  • Is there some kind of roadmap for the next months what will be worked on?

Write tests for JWT client assertions

Currently, we have no tests for the JWT client assertion feature.
The test(s) should test more than one assertion type (JWS type).

E.g. RS256
(default), RS512, ES{256,512}, PS{256,512}

Rethink Logouts

Omejdn offers an endpoint /logout accepting GET and POST requests, as well as a request parameter post_logout_redirect_uri. This bears some similarities to the end_session_endpoint defined in OIDC RP-Initiated Logout.
However, where RPIL has at least some security built in with regards to several attacks, including

  • Using the OP as an open redirector, and
  • Involuntarily logging out the user from arbitrary services,

Omejdn has none. In fact, Omejdn is simply deleting the user's login session before redirecting the user back to whatever URL was passed as a parameter.

Going with the terminology of the above draft, a user thinks of "logging out at a RP" as revoking any access rights of an RP via the OP. This is trickier than implementing RPIL, since RPIL only covers OpenID Sessions (to log out, a RP will send an id_token_hint) and a user will likely want to be able to revoke access of arbitrary OAuth capable services, likely via an Omejdn GUI. This in turn requires proper token revocation and optionally a method to notify OIDC RPs (such as OIDC Front/Backchannel Logout).

For the time being, the following should be implemented:

  • OIDC RPIL as open-redirect protection.
  • A logout confirmation page

How to request an access token?

The part "Requesting an access token", which was very helpful, has been removed from the main readme with #49. Where can this information be found now?

Client Certificate Revocation Checks

We only check client certificates for expiration atm. At some point we may want to consider checking their validity properly, which includes checking Revocation Lists.

Problems:

  • Our current trust model is: If it is registered in Omejdn, it is to be trusted until expiration.
  • Before supporting Revocation, we must first establish a way of defining trust in the root-CA.

Allow the service to issue Verifiable Credentials

We could add the option to issue verifiable credentials as defined in https://www.w3.org/TR/vc-data-model/#json-web-token in particular in the client_credentials flow using public key authentication (JWT bearer auth).
This would mean that we issue a verifiable credential in the vc claim of the JWT.
The VC could then be used by a client to create a new self-signed JWT which in turn includes a verifiable presentation claim (vp). The VC/VP attributes could be issued using Privacy-ABCs such as https://github.com/Fraunhofer-AISEC/libpabc.

Show requested Claims to User

The user must consent to granting scopes to a client in their name.
They should also consent to the requested individual Claims.

A client may request the equivalent of, say, the email scope by requesting the email and email_verified claims.
But in doing so it should not leave the user to make a less informed decision to consent.

Bug in KEYS_LOAD_ALL event of DefaultKeysDB

While searching the sourcecode for another issue, I found a bug:
I guess the KEYS_LOAD_ALL event should load all keys of the target_type. Then the 2 occurences of "keys/omejdn/#{f}" should maybe better be "#{KEYS_DIR}/#{target_type}/#{f}" to load the key from the correct directory.

omejdn-server/lib/keys.rb

Lines 121 to 132 in c767a7a

Dir.entries("#{KEYS_DIR}/#{target_type}").reject { |f| f.start_with? '.' }.map do |f|
result = {}
# The file could be either a certificate or a key
begin
result['certs'] = OpenSSL::X509::Certificate.load_file "keys/omejdn/#{f}"
result['pk'] = result['certs'][0].public_key
rescue StandardError
key = OpenSSL::PKey::RSA.new File.read("keys/omejdn/#{f}")
result['pk'] = key.public_key
end
result
end

HTTP-OPTION Requests result in Error

I encountered some CORS problems when using a front end. Everytime the browser sends OPTIONS request, OMEJDN throws an Exception: ERROR NoMethodError: undefined method upcase' for nil:NilClass` which might come from sinatra.

I fixed these problems by adding
return if request.env['REQUEST_METHOD'] == 'OPTIONS'
after
before '/api/v1/user*' do
and
before '/api/v1/config/*' do

Could you verify these issues?

Separate User selection from authentication

There are several OIDC Core requirements for which this is useful:

If the sub (subject) Claim is requested with a specific value for the ID Token, the Authorization Server MUST
only send a positive response if the End-User identified by that sub value has an active session with the
Authorization Server or has been Authenticated as a result of the request. The Authorization Server
MUST NOT reply with an ID Token or Access Token for a different user, even if they have an active session
with the Authorization Server. Such a request can be made either using an id_token_hint parameter or by
requesting a specific Claim Value as described in Section 5.5.1, if the claims parameter is supported by the
implementation. 
  • According to the prompt values in Section 3.1.2.1
select_account
    The Authorization Server SHOULD prompt the End-User to select a user account.

So we are supposed to support letting the user choose an account, as well as mandating one.

The easiest way I can see to do this is to have one screen to select an account, followed by a second screen to input a password.
Alternatively, we could reuse the existing form and deactivate the input field for the username.
The former approach would likely be more flexible, as it would allow the user to be logged into multiple accounts.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.