diff --git a/hiboo/application/base.py b/hiboo/application/base.py
index 5a4744a12cad2398b588330754039b76b591d951..dfa3f08584ed9b930368eb1f9eae934d0429a887 100644
--- a/hiboo/application/base.py
+++ b/hiboo/application/base.py
@@ -89,13 +89,24 @@ class BaseApplication(object):
             service=service
         )
 
-    def fill_service(self, service):
-        """ Updates the service options dictionary based on SSO
-        parameters
+    def populate_service(self, form, service):
+        """ Populate every form field in the service configuration,
+        then add application specific fields
         """
-        # TODO: replace this by returning a dict and updating
-        # service config, no need to pass the service object
-        return self.sso_protocol.fill_service(service)
+        form.populate_obj(service)
+        service.config.update({
+            field.name: field.data
+            for field in form
+            if not hasattr(BaseForm, field.name)
+        })
+        service.config.update(self.configure(form))
+        self.sso_protocol.setup(service)
+
+    def populate_form(self, service, form):
+        """ Populate every service configuration attribute in the
+        form
+        """
+        form.process(obj=service, **service.config)
 
     def apply_hooks(self, profile, transition, step):
         """ Apply hooks for a given transition and step
diff --git a/hiboo/application/infrastructure.py b/hiboo/application/infrastructure.py
index e74b12371995fd497b25269c91f7ff853bb713e4..9ebcacfb74d647b49f046f654d0b61dfade4db2b 100644
--- a/hiboo/application/infrastructure.py
+++ b/hiboo/application/infrastructure.py
@@ -14,23 +14,15 @@ class GitlabApplication(base.OIDCApplication):
         application_uri = fields.StringField(_("Gitlab URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
+    def configure(self, form):
         callback_uri = form.application_uri.data + "/users/auth/openid_connect/callback"
-        service.config.update({
-            "application_uri": form.application_uri.data,
+        return {
             "token_endpoint_auth_method": "client_secret_post",
             "redirect_uris": [callback_uri],
             "grant_types": ["authorization_code"],
             "response_types": ["code"],
             "special_mappings": ["mask_sub_uuid"]
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
+        }
 
 
 @register("grafana")
@@ -44,20 +36,12 @@ class GrafanaApplication(base.OIDCApplication):
         application_uri = fields.StringField(_("Grafana URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
+    def configure(self, form):
         callback_uri = form.application_uri.data + "/login/generic_oauth"
-        service.config.update({
-            "application_uri": form.application_uri.data,
+        return {
             "token_endpoint_auth_method": "client_secret_post",
             "redirect_uris": [callback_uri],
             "grant_types": ["authorization_code"],
             "response_types": ["code"],
             "special_mappings": []
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
+        }
diff --git a/hiboo/application/social.py b/hiboo/application/social.py
index e47678a25e854b78db074ab9d1467b91ff30fcb4..f5aa0906336420922d540d3b86fdf222789619cb 100644
--- a/hiboo/application/social.py
+++ b/hiboo/application/social.py
@@ -18,21 +18,13 @@ class MastodonApplication(base.SAMLApplication):
         application_uri = fields.StringField(_("Mastodon URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
-        callback_uri = form.application_uri.data + "/auth/auth/callback"
-        service.config.update({
-            "application_uri": form.application_uri.data,
+    def configure(self, form):
+        callback_uri = self.application_uri.data + "/auth/auth/callback"
+        return {
             "acs": callback_uri,
             "entityid": callback_uri,
             "sign_mode": "assertion"
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
+        }
 
 
 @register("synapse")
@@ -44,25 +36,15 @@ class SynapseApplication(base.SAMLApplication):
 
     class Form(base.BaseForm):
         application_uri = fields.StringField(_("Synapse homeserver URL"), [validators.URL(require_tld=False)])
-        admin_token = fields.PasswordField(_("Synapse administrator token"))
+        admin_token = fields.StringField(_("Synapse administrator token"))
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
-        service.config.update({
-            "application_uri": form.application_uri.data,
-            "admin_token": form.admin_token.data,
+    def configure(self, form):
+        return {
             "acs": form.application_uri.data + "/_matrix/saml2/authn_response",
             "entityid": form.application_uri.data + "/_matrix/saml2/metadata.xml",
             "sign_mode": "response"
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri"),
-            admin_token=service.config.get("admin_token")
-        )
+        }
 
     def get_axon(self, service):
         """ Return an axon instance for the homeserver
@@ -123,10 +105,9 @@ class WriteFreelyApplication(base.OIDCApplication):
         application_uri = fields.StringField(_("WriteFreely URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def configure(self, form, service):
+    def configure(self, form):
         callback_uri = form.application_uri.data + "/oauth/callback/generic"
         return {
-            "application_uri": form.application_uri.data,
             "token_endpoint_auth_method": "client_secret_basic",
             "redirect_uris": [callback_uri],
             "grant_types": ["authorization_code"],
@@ -134,12 +115,6 @@ class WriteFreelyApplication(base.OIDCApplication):
             "special_mappings": ["ignore_scopes"]
         }
 
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
-
 
 @register("peertube")
 class PeertubeApplication(base.OIDCApplication):
@@ -152,18 +127,11 @@ class PeertubeApplication(base.OIDCApplication):
         application_uri = fields.StringField(_("PeerTube URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def configure(self, form, service):
+    def configure(self, form):
         callback_uri = form.application_uri.data + "/plugins/auth-openid-connect/router/code-cb"
         return {
-            "application_uri": form.application_uri.data,
             "token_endpoint_auth_method": "client_secret_basic",
             "redirect_uris": [callback_uri],
             "grant_types": ["authorization_code"],
             "response_types": ["code"],
         }
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
\ No newline at end of file
diff --git a/hiboo/application/sso.py b/hiboo/application/sso.py
index bc10bb8dc18769ca92ef08b62a660e494e2ce5e0..5c1d51779956834c7e947924dc2ea7bd8def0915 100644
--- a/hiboo/application/sso.py
+++ b/hiboo/application/sso.py
@@ -42,25 +42,10 @@ class GenericOIDCApplication(base.OIDCApplication):
         )
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
-        service.config.update({
-            "token_endpoint_auth_method": form.token_endpoint_auth_method.data,
+    def configure(self, form):
+        return {
             "redirect_uris": [form.redirect_uri.data],
-            "grant_types": form.grant_types.data,
-            "response_types": form.response_types.data,
-            "special_mappings": form.special_mappings.data
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            token_endpoint_auth_method=service.config.get("token_endpoint_auth_method"),
-            redirect_uri=service.config.get("redirect_uris", [""])[0],
-            grant_types=service.config.get("grant_types", ["authorization_code"]),
-            response_types=service.config.get("response_types", ["code"]),
-            special_mappings=service.config.get("special_mappings", [])
-        )
+        }
 
 
 @register("saml")
@@ -81,18 +66,5 @@ class GenericSAMLApplication(base.SAMLApplication):
         )
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
-        service.config.update({
-            "acs": form.acs.data,
-            "entityid": form.entityid.data,
-            "sign_mode": form.sign_mode.data
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            acs=service.config.get("acs"),
-            entityid=service.config.get("entityid"),
-            sign_mode=service.config.get("sign_mode")
-        )
\ No newline at end of file
+    def configure(self, form):
+        return {}
diff --git a/hiboo/application/storage.py b/hiboo/application/storage.py
index 99b8d3002a5508672b37bf26e453847d759a7ec8..4142da988b906db8ffc0c5da16562f1e85c6eeb5 100644
--- a/hiboo/application/storage.py
+++ b/hiboo/application/storage.py
@@ -14,20 +14,12 @@ class SeafileApplication(base.SAMLApplication):
         application_uri = fields.StringField(_("NextCloud URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
-        service.config.update({
-            "application_uri": form.application_uri.data,
+    def configure(self, form):
+        return {
             "acs": form.application_uri.data + "/apps/user_saml/saml/acs",
             "entityid": form.application_uri.data + "/apps/user_saml/saml/metadata",
             "sign_mode": "response"
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
+        }
 
 
 @register("seafile")
@@ -41,20 +33,12 @@ class SeafileApplication(base.OIDCApplication):
         application_uri = fields.StringField(_("Seafile URL"), [validators.URL(require_tld=False)])
         submit = fields.SubmitField(_('Submit'))
 
-    def populate_service(self, form, service):
+    def configure(self, form):
         callback_uri = form.application_uri.data + "/oauth/callback"
-        service.config.update({
-            "application_uri": form.application_uri.data,
+        return {
             "token_endpoint_auth_method": "client_secret_basic",
             "redirect_uris": [callback_uri],
             "grant_types": ["authorization_code"],
             "response_types": ["code"],
             "special_mappings": []
-        })
-        self.fill_service(service)
-
-    def populate_form(self, service, form):
-        form.process(
-            obj=service,
-            application_uri=service.config.get("application_uri")
-        )
+        }
diff --git a/hiboo/service/views.py b/hiboo/service/views.py
index beb241bbc2afe2784e7135a47924b53593e6ea38..742b26bf14ad4ddef274bbc6a44b150bf4771bb0 100644
--- a/hiboo/service/views.py
+++ b/hiboo/service/views.py
@@ -35,7 +35,6 @@ def create(application_id):
         service.application_id = application_id
         service.uuid = str(uuid.uuid4())
         service.config = {}
-        form.populate_obj(service)
         app.populate_service(form, service)
         models.db.session.add(service)
         models.db.session.commit()
@@ -52,7 +51,6 @@ def edit(service_uuid):
     app = service.application or flask.abort(404)
     form = app.Form()
     if form.validate_on_submit():
-        form.populate_obj(service)
         app.populate_service(form, service)
         models.db.session.commit()
         flask.flash(_("Service successfully updated"), "success")
diff --git a/hiboo/sso/oidc.py b/hiboo/sso/oidc.py
index 23a27654c41affc8b66e9716137fb334511a72d2..2fa3242b8bb299faafe90ccfe9298ce590897668 100644
--- a/hiboo/sso/oidc.py
+++ b/hiboo/sso/oidc.py
@@ -22,7 +22,7 @@ import uuid
 RSA_KEY_LENGTH = 2048
 
 
-def fill_service(service):
+def setup(service):
     """ If necessary, prepare the client with cryptographic material.
     """
     if "client_id" not in service.config:
diff --git a/hiboo/sso/saml.py b/hiboo/sso/saml.py
index 4905a4c97afd767ed27b25f5a37781f752dac920..83f947418f3e9a58af97e2d6248d3bfc5e9a8645 100644
--- a/hiboo/sso/saml.py
+++ b/hiboo/sso/saml.py
@@ -21,7 +21,7 @@ IDP_CERT_NAME = "{}-idp"
 SP_CERT_NAME = "{}-sp"
 
 
-def fill_service(service):
+def setup(service):
     if "idp_cert" not in service.config:
         key, _, cert = common.generate_rsa_certificate(IDP_CERT_NAME.format(service.uuid))
         service.config.update({"idp_key": key, "idp_cert": cert})