Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased

# OIDC and KML support release

To configure your OIDC provider, set the following environment variables:

```
OIDC_CLIENT_ID=client_id_example
OIDC_CLIENT_SECRET=client_secret_example
OIDC_ISSUER=https://authentik.yourdomain.com/application/o/dawarich/
OIDC_REDIRECT_URI=https://your-dawarich-url.com/users/auth/openid_connect/callback
```

## Added

- Support for KML file uploads. #350
Expand All @@ -18,6 +29,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed

- Internal redis settings updated to implement support for connecting to Redis via unix socket. #1706
- Implemented authentication via GitHub and Google for Dawarich Cloud.
- Implemented OpenID Connect authentication for self-hosted Dawarich instances. #66


# [0.35.1] - 2025-11-09

Expand Down
6 changes: 5 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby File.read('.ruby-version').strip

gem 'activerecord-postgis-adapter', '~> 11.0'
gem 'activerecord-postgis-adapter', '11.0'
# https://meta.discourse.org/t/cant-rebuild-due-to-aws-sdk-gem-bump-and-new-aws-data-integrity-protections/354217/40
gem 'aws-sdk-core', '~> 3.215.1', require: false
gem 'aws-sdk-kms', '~> 1.96.0', require: false
Expand All @@ -24,6 +24,10 @@ gem 'jwt', '~> 2.8'
gem 'kaminari'
gem 'lograge'
gem 'oj'
gem 'omniauth-github', '~> 2.0.0'
gem 'omniauth-google-oauth2'
gem 'omniauth_openid_connect'
gem 'omniauth-rails_csrf_protection'
gem 'parallel'
gem 'pg'
gem 'prometheus_exporter'
Expand Down
99 changes: 98 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ GEM
uri (>= 0.13.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
aes_key_wrap (1.1.0)
ast (2.4.3)
attr_extras (7.1.0)
attr_required (1.0.2)
aws-eventstream (1.3.2)
aws-partitions (1.1072.0)
aws-sdk-core (3.215.1)
Expand All @@ -108,6 +110,7 @@ GEM
bcrypt (3.1.20)
benchmark (0.4.1)
bigdecimal (3.3.1)
bindata (2.5.1)
bootsnap (1.18.6)
msgpack (~> 1.2)
brakeman (7.1.0)
Expand Down Expand Up @@ -161,6 +164,8 @@ GEM
dotenv (= 3.1.8)
railties (>= 6.1)
drb (2.2.3)
email_validator (2.2.4)
activemodel
erb (5.1.3)
erubi (1.13.1)
et-orbi (1.4.0)
Expand All @@ -171,6 +176,14 @@ GEM
factory_bot (~> 6.5)
railties (>= 6.1.0)
fakeredis (0.1.4)
faraday (2.14.0)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-follow_redirects (0.4.0)
faraday (>= 1, < 3)
faraday-net_http (3.4.1)
net-http (>= 0.5.0)
ffaker (2.25.0)
ffi (1.17.2-aarch64-linux-gnu)
ffi (1.17.2-arm-linux-gnu)
Expand All @@ -196,6 +209,7 @@ GEM
rgeo-geojson (~> 2.1)
zeitwerk (~> 2.5)
hashdiff (1.1.2)
hashie (5.0.0)
httparty (0.23.1)
csv
mini_mime (>= 1.0.0)
Expand All @@ -213,6 +227,13 @@ GEM
reline (>= 0.4.2)
jmespath (1.6.2)
json (2.15.0)
json-jwt (1.17.0)
activesupport (>= 4.2)
aes_key_wrap
base64
bindata
faraday (~> 2.0)
faraday-follow_redirects
json-schema (5.0.1)
addressable (~> 2.8)
jwt (2.10.1)
Expand Down Expand Up @@ -256,6 +277,8 @@ GEM
multi_json (1.15.0)
multi_xml (0.7.1)
bigdecimal (~> 3.1)
net-http (0.6.0)
uri
net-imap (0.5.12)
date
net-protocol
Expand All @@ -279,9 +302,52 @@ GEM
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-gnu)
racc (~> 1.4)
oauth2 (2.0.17)
faraday (>= 0.17.3, < 4.0)
jwt (>= 1.0, < 4.0)
logger (~> 1.2)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
snaky_hash (~> 2.0, >= 2.0.3)
version_gem (~> 1.1, >= 1.1.9)
oj (3.16.11)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (2.1.4)
hashie (>= 3.4.6)
logger
rack (>= 2.2.3)
rack-protection
omniauth-github (2.0.1)
omniauth (~> 2.0)
omniauth-oauth2 (~> 1.8)
omniauth-google-oauth2 (1.2.1)
jwt (>= 2.9.2)
oauth2 (~> 2.0)
omniauth (~> 2.0)
omniauth-oauth2 (~> 1.8)
omniauth-oauth2 (1.8.0)
oauth2 (>= 1.4, < 3)
omniauth (~> 2.0)
omniauth-rails_csrf_protection (1.0.2)
actionpack (>= 4.2)
omniauth (~> 2.0)
omniauth_openid_connect (0.8.0)
omniauth (>= 1.9, < 3)
openid_connect (~> 2.2)
openid_connect (2.3.1)
activemodel
attr_required (>= 1.0.0)
email_validator
faraday (~> 2.0)
faraday-follow_redirects
json-jwt (>= 1.16)
mail
rack-oauth2 (~> 2.2)
swd (~> 2.0)
tzinfo
validate_url
webfinger (~> 2.0)
optimist (3.2.1)
orm_adapter (0.5.0)
ostruct (0.6.1)
Expand Down Expand Up @@ -321,6 +387,17 @@ GEM
raabro (1.4.0)
racc (1.8.1)
rack (3.2.3)
rack-oauth2 (2.3.0)
activesupport
attr_required
faraday (~> 2.0)
faraday-follow_redirects
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (4.2.1)
base64 (>= 0.1.0)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-session (2.1.1)
base64 (>= 0.1.0)
rack (>= 3.0.0)
Expand Down Expand Up @@ -475,6 +552,9 @@ GEM
simplecov_json_formatter (~> 0.1)
simplecov-html (0.13.1)
simplecov_json_formatter (0.1.4)
snaky_hash (2.0.3)
hashie (>= 0.1.0, < 6)
version_gem (>= 1.1.8, < 3)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
Expand All @@ -492,6 +572,11 @@ GEM
attr_extras (>= 6.2.4)
diff-lcs
patience_diff
swd (2.0.3)
activesupport (>= 3)
attr_required (>= 0.0.5)
faraday (~> 2.0)
faraday-follow_redirects
tailwindcss-rails (3.3.2)
railties (>= 7.0.0)
tailwindcss-ruby (~> 3.0)
Expand All @@ -515,8 +600,16 @@ GEM
unicode-emoji (4.1.0)
uri (1.0.4)
useragent (0.16.11)
validate_url (1.0.15)
activemodel (>= 3.0.0)
public_suffix
version_gem (1.1.9)
warden (1.2.9)
rack (>= 2.0.9)
webfinger (2.1.3)
activesupport
faraday (~> 2.0)
faraday-follow_redirects
webmock (3.25.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
Expand All @@ -540,7 +633,7 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
activerecord-postgis-adapter (~> 11.0)
activerecord-postgis-adapter (= 11.0)
aws-sdk-core (~> 3.215.1)
aws-sdk-kms (~> 1.96.0)
aws-sdk-s3 (~> 1.177.0)
Expand Down Expand Up @@ -568,6 +661,10 @@ DEPENDENCIES
kaminari
lograge
oj
omniauth-github (~> 2.0.0)
omniauth-google-oauth2
omniauth-rails_csrf_protection
omniauth_openid_connect
parallel
pg
prometheus_exporter
Expand Down
54 changes: 54 additions & 0 deletions app/controllers/users/omniauth_callbacks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def github
handle_auth('GitHub')
end

def google_oauth2
handle_auth('Google')
end

def openid_connect
handle_auth('OpenID Connect')
end

def failure
error_type = request.env['omniauth.error.type']
error = request.env['omniauth.error']

# Provide user-friendly error messages
error_message =
case error_type
when :invalid_credentials
'Invalid credentials. Please check your username and password.'
when :timeout
'Connection timeout. Please try again.'
when :csrf_detected
'Security error detected. Please try again.'
else
if error&.message&.include?('Discovery')
'Unable to connect to authentication provider. Please contact your administrator.'
elsif error&.message&.include?('Issuer mismatch')
'Authentication provider configuration error. Please contact your administrator.'
else
"Authentication failed: #{params[:message] || error&.message || 'Unknown error'}"
end
end

redirect_to root_path, alert: error_message
end

private

def handle_auth(provider)
@user = User.from_omniauth(request.env['omniauth.auth'])

if @user.persisted?
flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: provider
sign_in_and_redirect @user, event: :authentication
else
redirect_to new_user_registration_url, alert: @user.errors.full_messages.join("\n")
end
end
end
37 changes: 37 additions & 0 deletions app/models/concerns/omniauthable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

module Omniauthable
extend ActiveSupport::Concern

class_methods do
def from_omniauth(access_token)
data = access_token.info
provider = access_token.provider
uid = access_token.uid

# First, try to find user by provider and uid (for linked accounts)
user = find_by(provider: provider, uid: uid)

return user if user

# If not found, try to find by email
user = find_by(email: data['email'])

if user
# Update provider and uid for existing user (first-time linking)
user.update(provider: provider, uid: uid)
return user
end

# Create new user if not found
user = create(
email: data['email'],
password: Devise.friendly_token[0, 20],
provider: provider,
uid: uid
)

user
end
end
end
5 changes: 4 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

class User < ApplicationRecord # rubocop:disable Metrics/ClassLength
include UserFamily
include Omniauthable

devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :trackable
:recoverable, :rememberable, :validatable, :trackable,
:omniauthable, omniauth_providers: ::OMNIAUTH_PROVIDERS

has_many :points, dependent: :destroy
has_many :imports, dependent: :destroy
Expand Down
4 changes: 2 additions & 2 deletions app/views/devise/registrations/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@
<div class="form-control mt-6">
<%= f.submit "Update", class: 'btn btn-primary' %>
</div>

<%= render "devise/shared/links" %>
<% end %>

<%= render "devise/shared/links" %>

<p class='mt-3'>Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { turbo_confirm: "Are you sure?", turbo_method: :delete }, method: :delete, class: 'btn' %></p>
<div class="divider"></div>
<p class='mt-3 flex flex-col gap-2'>
Expand Down
6 changes: 3 additions & 3 deletions app/views/devise/registrations/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@
<%= f.submit (@invitation ? "Create Account & Join Family" : "Sign up"),
class: 'btn btn-primary' %>
</div>
<% end %>

<% unless @invitation %>
<%= render "devise/shared/links" %>
<% end %>
<% unless @invitation %>
<%= render "devise/shared/links" %>
<% end %>
</div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions app/views/devise/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
<div class="form-control mt-6">
<%= f.submit (@invitation ? "Sign in & Accept Invitation" : "Log in"), class: 'btn btn-primary' %>
</div>
<% end %>

<% unless @invitation %>
<%= render "devise/shared/links" %>
<% end %>
<% unless @invitation %>
<%= render "devise/shared/links" %>
<% end %>
</div>
</div>
Expand Down
Loading
Loading