💭

Rails と Okta で SCIM 機能を実装してみた(後半)

2023/04/11に公開

概要

こちらの記事の続きになります。今回はユーザーの編集、削除機能を実装していきたいと思います。

今回作成したものは以下になります。
https://github.com/kazu-2020/okta-playground/tree/main/api

事前準備

前の記事で作成したアプリケーションを利用したいと思います。今回は、編集、削除を実装していくので下図のようにUpdate User Attributes Deactivate Usersを有効化します。

編集機能の実装

Okta ではカスタムアプリケーションの場合、全てPUTリクエストで送信が行われます。

For any custom app integrations created using the AIW,
all SCIM operations that update a User object,
including these operations, are always sent through a PUT method request.

https://developer.okta.com/docs/reference/scim/scim-20/#update-a-specific-user-patch

それを踏まえて routes.rb にルーティングを追加します。

Rails.application.routes.draw do
  namespace :scim_v2 do
    ...
    put 'Users/:id', to: 'users#replace'
  end
end

次にコントローラーに replace アクションを実装していきます。
親クラスの実装は以下のようになっており、 create アクションと似た実装になっています。
https://github.com/RIPAGlobal/scimitar/blob/fe26bad339863b3b1fbb64112baf39e9b214798c/app/controllers/scimitar/resources_controller.rb#L85-L97

実際のコントローラの実装は以下のようにシンプルな実装になります。

module ScimV2
  class UsersController < Scimitar::ResourcesController
    def replace
      super do |record_id, scim_resource|
        user = storage_class.find(record_id)
        user.save_from_scim!(scim_resource)

        user.to_scim(location: url_for(action: :show, id: user.id))
      end
    end
  end
end

動作確認を行いたいと思います。今回は、田中太郎というユーザーの Primary email を tanakataro@example.comからupdate-tanakataro@example.comに更新して、保存します。

ログは以下のようになり、email が更新できていることが確認できます。また、Okta の SCIM プロトコルにある Update a specific User(PUT)のフロー図と処理が同じであることが確認できます。



https://developer.okta.com/docs/reference/scim/scim-20/#update-a-specific-user-put

削除機能の実装

Okta ではアプリケーションからユーザーを削除した場合、DELETE リクエストではなく、PUTリクエストが送信されます。この時、リクエストパラメータのactive属性にfalseがセットされて渡されます。

https://developer.okta.com/docs/reference/scim/scim-20/#delete-users

今回はアプリケーションからユーザーが削除された場合、DBからは物理削除を行うという仕様で実装します。そのため、先ほど実装した replace アクションを以下のように修正します。

module ScimV2
  class UsersController < Scimitar::ResourcesController
    def replace
      super do |record_id, scim_resource|
        user = storage_class.find(record_id)
-        user.save_from_scim!(scim_resource)
+        scim_resource.active ? user.save_from_scim!(scim_resource) : user.destroy!


        user.to_scim(location: url_for(action: :show, id: user.id))
      end
    end
  end
end

userNameを変更した場合

Okta ではユーザーの一意性をuserName属性で確認します。しかし、Okta のダッシュボードでは各ユーザーの userName を後から変更できます。その場合、Okta SCIM プロトコルでは 最初にDelete Usersが実行され、次にCreate Usersが実行されます。

https://developer.okta.com/docs/reference/scim/scim-20/#delete-users

https://developer.okta.com/docs/reference/scim/scim-20/#create-users

ログでも確認することができます。

参考

https://github.com/RIPAGlobal/scimitar#data-models
https://developer.okta.com/docs/reference/scim/scim-20/

Discussion