diff --git a/internal/db/dbmigrate/scripts/v0.4.0.pre.sql b/internal/db/dbmigrate/scripts/v0.4.0.pre.sql
index 8275d1c5e54cdf2343e34aa999c6bc87dc87ca67..345a187a61c38517e8d8fb008ce9027f0138ce16 100644
--- a/internal/db/dbmigrate/scripts/v0.4.0.pre.sql
+++ b/internal/db/dbmigrate/scripts/v0.4.0.pre.sql
@@ -1,69 +1,5 @@
 # noinspection SqlResolveForFile
 
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
-# noinspection SqlResolveForFile
-
 # Tables
 DROP VIEW IF EXISTS MyTokens;
 
@@ -75,6 +11,26 @@ ALTER TABLE Users
 ALTER TABLE TransferCodesAttributes
     ADD ssh_key_hash VARCHAR(128) NULL;
 
+TRUNCATE TABLE AuthInfo;
+ALTER TABLE AuthInfo
+    ADD request_json JSON NOT NULL;
+ALTER TABLE AuthInfo
+    DROP COLUMN iss;
+ALTER TABLE AuthInfo
+    DROP COLUMN restrictions;
+ALTER TABLE AuthInfo
+    DROP COLUMN capabilities;
+ALTER TABLE AuthInfo
+    DROP COLUMN name;
+ALTER TABLE AuthInfo
+    DROP COLUMN subtoken_capabilities;
+ALTER TABLE AuthInfo
+    DROP COLUMN rotation;
+ALTER TABLE AuthInfo
+    DROP COLUMN response_type;
+ALTER TABLE AuthInfo
+    DROP COLUMN max_token_len;
+
 # CryptStore
 CREATE TABLE `CryptPayloadTypes`
 (
@@ -260,31 +216,19 @@ END;;
 CREATE OR REPLACE PROCEDURE AuthInfo_Get(IN STATE TEXT)
 BEGIN
     SELECT state_h,
-           iss,
-           restrictions,
-           capabilities,
-           subtoken_capabilities,
-           name,
+           request_json,
            polling_code,
-           rotation,
-           response_type,
-           max_token_len,
            code_verifier
         FROM AuthInfo
         WHERE state_h = STATE
           AND expires_at >= CURRENT_TIMESTAMP();
 END;;
 
-CREATE OR REPLACE PROCEDURE AuthInfo_Insert(IN STATE_H_ VARCHAR(128), IN ISS_ TEXT, IN RESTRICTIONS_ LONGTEXT,
-                                            IN CAPABILITIES_ LONGTEXT, IN SUBTOKEN_CAPABILITIES_ LONGTEXT,
-                                            IN NAME_ TEXT,
-                                            IN EXPIRES_IN_ INT, IN POLLING_CODE_ BIT, IN ROTATION_ LONGTEXT,
-                                            IN RESPONSE_TYPE_ VARCHAR(128), IN MAX_TOKEN_LEN_ INT)
+CREATE OR REPLACE PROCEDURE AuthInfo_Insert(IN STATE_H_ VARCHAR(128), IN REQUEST LONGTEXT,
+                                            IN EXPIRES_IN_ INT, IN POLLING_CODE_ BIT)
 BEGIN
-    INSERT INTO AuthInfo (`state_h`, `iss`, `restrictions`, `capabilities`, `subtoken_capabilities`, `name`,
-                          `expires_in`, `polling_code`, `rotation`, `response_type`, `max_token_len`)
-        VALUES (STATE_H_, ISS_, RESTRICTIONS_, CAPABILITIES_, SUBTOKEN_CAPABILITIES_, NAME_, EXPIRES_IN_, POLLING_CODE_,
-                ROTATION_, RESPONSE_TYPE_, MAX_TOKEN_LEN_);
+    INSERT INTO AuthInfo (`state_h`, `request_json`, `expires_in`, `polling_code`)
+        VALUES (STATE_H_, REQUEST, EXPIRES_IN_, POLLING_CODE_);
 END;;
 
 CREATE OR REPLACE PROCEDURE AuthInfo_SetCodeVerifier(IN STATE TEXT, IN VERIFIER TEXT)
@@ -292,15 +236,10 @@ BEGIN
     UPDATE AuthInfo SET code_verifier = VERIFIER WHERE state_h = STATE;
 END;;
 
-CREATE OR REPLACE PROCEDURE AuthInfo_Update(IN STATE TEXT, IN RESTRICTIONS_ LONGTEXT, IN CAPABILITIES_ LONGTEXT,
-                                            IN SUBTOKEN_CAPABILITIES_ LONGTEXT, IN ROTATION_ LONGTEXT, IN NAME_ TEXT)
+CREATE OR REPLACE PROCEDURE AuthInfo_Update(IN STATE TEXT, IN REQUEST LONGTEXT)
 BEGIN
     UPDATE AuthInfo
-    SET restrictions          = RESTRICTIONS_,
-        capabilities          = CAPABILITIES_,
-        subtoken_capabilities = SUBTOKEN_CAPABILITIES_,
-        rotation              = ROTATION_,
-        name                  = NAME_
+    SET request_json = REQUEST
         WHERE state_h = STATE;
 END;;
 
diff --git a/internal/db/dbrepo/authcodeinforepo/authcodeInfo.go b/internal/db/dbrepo/authcodeinforepo/authcodeInfo.go
index 9f944f8d43305163808ed1b520a92aec31eace77..535ff71a95192933c3926a2af8ba0747f2475f39 100644
--- a/internal/db/dbrepo/authcodeinforepo/authcodeInfo.go
+++ b/internal/db/dbrepo/authcodeinforepo/authcodeInfo.go
@@ -5,12 +5,11 @@ import (
 	"github.com/pkg/errors"
 	log "github.com/sirupsen/logrus"
 
-	"github.com/oidc-mytoken/server/shared/model"
-	"github.com/oidc-mytoken/server/shared/utils"
+	"github.com/oidc-mytoken/server/internal/config"
+	"github.com/oidc-mytoken/server/internal/endpoints/token/mytoken/pkg"
 
 	"github.com/oidc-mytoken/api/v0"
 
-	"github.com/oidc-mytoken/server/internal/config"
 	"github.com/oidc-mytoken/server/internal/db"
 	"github.com/oidc-mytoken/server/internal/db/dbrepo/authcodeinforepo/state"
 	"github.com/oidc-mytoken/server/internal/db/dbrepo/mytokenrepo/transfercoderepo"
@@ -25,67 +24,34 @@ type AuthFlowInfo struct {
 
 // AuthFlowInfoOut holds database information about a started authorization flow
 type AuthFlowInfoOut struct {
-	State                *state.State
-	Issuer               string
-	Restrictions         restrictions.Restrictions
-	Capabilities         api.Capabilities
-	SubtokenCapabilities api.Capabilities
-	Name                 string
-	PollingCode          bool
-	Rotation             *api.Rotation
-	ResponseType         model.ResponseType
-	MaxTokenLen          int
-	CodeVerifier         string
+	State *state.State
+	pkg.AuthCodeFlowRequest
+	PollingCode  bool
+	CodeVerifier string
 }
 
 type authFlowInfo struct {
-	State                *state.State `db:"state_h"`
-	Issuer               string       `db:"iss"`
-	Restrictions         restrictions.Restrictions
-	Capabilities         api.Capabilities
-	SubtokenCapabilities api.Capabilities `db:"subtoken_capabilities"`
-	Name                 db.NullString
-	PollingCode          db.BitBool `db:"polling_code"`
-	ExpiresIn            int64      `db:"expires_in"`
-	Rotation             *api.Rotation
-	ResponseType         model.ResponseType `db:"response_type"`
-	MaxTokenLen          *int               `db:"max_token_len"`
-	CodeVerifier         db.NullString      `db:"code_verifier"`
+	State                   *state.State `db:"state_h"`
+	pkg.AuthCodeFlowRequest `db:"request_json"`
+	PollingCode             db.BitBool    `db:"polling_code"`
+	CodeVerifier            db.NullString `db:"code_verifier"`
 }
 
 func (i *AuthFlowInfo) toAuthFlowInfo() *authFlowInfo {
 	return &authFlowInfo{
-		State:                i.State,
-		Issuer:               i.Issuer,
-		Restrictions:         i.Restrictions,
-		Capabilities:         i.Capabilities,
-		SubtokenCapabilities: i.SubtokenCapabilities,
-		Name:                 db.NewNullString(i.Name),
-		ExpiresIn:            config.Get().Features.Polling.PollingCodeExpiresAfter,
-		PollingCode:          i.PollingCode != nil,
-		Rotation:             i.Rotation,
-		ResponseType:         i.ResponseType,
-		MaxTokenLen:          utils.NewInt(i.MaxTokenLen),
+		State:               i.State,
+		AuthCodeFlowRequest: i.AuthCodeFlowRequest,
+		PollingCode:         i.PollingCode != nil,
 	}
 }
 
 func (i *authFlowInfo) toAuthFlowInfo() *AuthFlowInfoOut {
-	o := &AuthFlowInfoOut{
-		State:                i.State,
-		Issuer:               i.Issuer,
-		Restrictions:         i.Restrictions,
-		Capabilities:         i.Capabilities,
-		SubtokenCapabilities: i.SubtokenCapabilities,
-		Name:                 i.Name.String,
-		PollingCode:          bool(i.PollingCode),
-		Rotation:             i.Rotation,
-		ResponseType:         i.ResponseType,
-		CodeVerifier:         i.CodeVerifier.String,
+	return &AuthFlowInfoOut{
+		State:               i.State,
+		AuthCodeFlowRequest: i.AuthCodeFlowRequest,
+		PollingCode:         bool(i.PollingCode),
+		CodeVerifier:        i.CodeVerifier.String,
 	}
-	if i.MaxTokenLen != nil {
-		o.MaxTokenLen = *i.MaxTokenLen
-	}
-	return o
 }
 
 // Store stores the AuthFlowInfoIn in the database as well as the linked polling code if it exists
@@ -99,9 +65,9 @@ func (i *AuthFlowInfo) Store(rlog log.Ext1FieldLogger, tx *sqlx.Tx) error {
 					return err
 				}
 			}
-			_, err := tx.NamedExec(
-				`CALL AuthInfo_Insert(:state_h, :iss, :restrictions, :capabilities, :subtoken_capabilities, :name, :expires_in, :polling_code, :rotation, :response_type, :max_token_len)`,
-				store,
+			_, err := tx.Exec(
+				`CALL AuthInfo_Insert(?, ?, ?, ?)`, store.State, store.AuthCodeFlowRequest,
+				config.Get().Features.Polling.PollingCodeExpiresAfter, store.PollingCode,
 			)
 			return errors.WithStack(err)
 		},
@@ -113,7 +79,15 @@ func GetAuthFlowInfoByState(rlog log.Ext1FieldLogger, state *state.State) (*Auth
 	info := authFlowInfo{}
 	if err := db.Transact(
 		rlog, func(tx *sqlx.Tx) error {
-			return errors.WithStack(tx.Get(&info, `CALL AuthInfo_Get(?)`, state))
+			row := tx.QueryRowx(`CALL AuthInfo_Get(?)`, state)
+			if err := row.Err(); err != nil {
+				return errors.WithStack(err)
+			}
+			return errors.WithStack(
+				row.Scan(
+					&info.State, &info.AuthCodeFlowRequest, &info.PollingCode, &info.CodeVerifier,
+				),
+			)
 		},
 	); err != nil {
 		return nil, err
@@ -138,9 +112,18 @@ func UpdateTokenInfoByState(
 ) error {
 	return db.RunWithinTransaction(
 		rlog, tx, func(tx *sqlx.Tx) error {
-			_, err := tx.Exec(
-				`CALL AuthInfo_Update(?,?,?,?,?,?)`,
-				state, r, c, sc, rot, tokenName,
+			info, err := GetAuthFlowInfoByState(rlog, state)
+			if err != nil {
+				return err
+			}
+			info.Restrictions = r
+			info.Capabilities = c
+			info.SubtokenCapabilities = sc
+			info.Rotation = rot
+			info.Name = tokenName
+			_, err = tx.Exec(
+				`CALL AuthInfo_Update(?,?)`,
+				state, info.AuthCodeFlowRequest,
 			)
 			return errors.WithStack(err)
 		},
diff --git a/internal/endpoints/token/mytoken/pkg/authCodeFlowRequest.go b/internal/endpoints/token/mytoken/pkg/authCodeFlowRequest.go
index e3f0a19147e66dcf99f9bf0831d008c0e1b17a66..cf1be4cf5fe11ab00981dcf50ebcbeffccb21359 100644
--- a/internal/endpoints/token/mytoken/pkg/authCodeFlowRequest.go
+++ b/internal/endpoints/token/mytoken/pkg/authCodeFlowRequest.go
@@ -1,6 +1,7 @@
 package pkg
 
 import (
+	"database/sql/driver"
 	"encoding/json"
 
 	"github.com/oidc-mytoken/api/v0"
@@ -11,6 +12,7 @@ import (
 type AuthCodeFlowRequest struct {
 	OIDCFlowRequest
 	RedirectType string `json:"redirect_type"`
+	RedirectURL  string `json:"redirect_url"`
 }
 
 // Native checks if the request is native
@@ -31,6 +33,22 @@ func (r *AuthCodeFlowRequest) UnmarshalJSON(data []byte) error {
 // MarshalJSON implements the json marshaler interface
 func (r *AuthCodeFlowRequest) MarshalJSON() ([]byte, error) {
 	r.redirectType = r.RedirectType
+	r.redirectURL = r.RedirectURL
 	data, err := json.Marshal(r.OIDCFlow)
 	return data, errors.WithStack(err)
 }
+
+// Scan implements the sql.Scanner interface
+func (r *AuthCodeFlowRequest) Scan(src interface{}) error {
+	v, ok := src.([]byte)
+	if !ok {
+		return errors.New("bad []byte type assertion")
+	}
+	return errors.WithStack(json.Unmarshal(v, r))
+}
+
+// Value implements the driver.Valuer interface
+func (r AuthCodeFlowRequest) Value() (driver.Value, error) {
+	v, err := json.Marshal(r)
+	return v, errors.WithStack(err)
+}
diff --git a/internal/endpoints/token/mytoken/pkg/oidcFlowRequest.go b/internal/endpoints/token/mytoken/pkg/oidcFlowRequest.go
index 6299b6265b4172aa4e2c2d39f3426d5defceec78..39de8c04e30ca00975807421f27f0ea48f414224 100644
--- a/internal/endpoints/token/mytoken/pkg/oidcFlowRequest.go
+++ b/internal/endpoints/token/mytoken/pkg/oidcFlowRequest.go
@@ -19,6 +19,7 @@ type OIDCFlowRequest struct {
 	Restrictions        restrictions.Restrictions `json:"restrictions"`
 	ResponseType        model.ResponseType        `json:"response_type"`
 	redirectType        string
+	redirectURL         string
 }
 
 // NewOIDCFlowRequest creates a new OIDCFlowRequest with default values where they can be omitted
@@ -40,15 +41,22 @@ func (r *OIDCFlowRequest) SetRedirectType(redirect string) {
 	r.redirectType = redirect
 }
 
+// SetRedirectURL sets the (hidden) redirect url
+func (r *OIDCFlowRequest) SetRedirectURL(url string) {
+	r.redirectURL = url
+}
+
 // MarshalJSON implements the json.Marshaler interface
 func (r OIDCFlowRequest) MarshalJSON() ([]byte, error) {
 	type ofr OIDCFlowRequest
 	o := struct {
 		ofr
 		RedirectType string `json:"redirect_type,omitempty"`
+		RedirectURL  string `json:"redirect_url,omitempty"`
 	}{
 		ofr:          ofr(r),
 		RedirectType: r.redirectType,
+		RedirectURL:  r.redirectURL,
 	}
 	data, err := json.Marshal(o)
 	return data, errors.WithStack(err)
@@ -60,14 +68,17 @@ func (r *OIDCFlowRequest) UnmarshalJSON(data []byte) error {
 	o := struct {
 		ofr
 		RedirectType string `json:"redirect_type"`
+		RedirectURL  string `json:"redirect_url"`
 	}{
 		ofr: ofr(*NewOIDCFlowRequest()),
 	}
 	o.RedirectType = o.redirectType
+	o.RedirectURL = o.redirectURL
 	if err := json.Unmarshal(data, &o); err != nil {
 		return errors.WithStack(err)
 	}
 	o.redirectType = o.RedirectType
+	o.redirectURL = o.RedirectURL
 	*r = OIDCFlowRequest(o.ofr)
 	if r.SubtokenCapabilities != nil && !r.Capabilities.Has(api.CapabilityCreateMT) {
 		r.SubtokenCapabilities = nil
@@ -80,6 +91,7 @@ func (r OIDCFlowRequest) ToAuthCodeFlowRequest() AuthCodeFlowRequest {
 	return AuthCodeFlowRequest{
 		OIDCFlowRequest: r,
 		RedirectType:    r.redirectType,
+		RedirectURL:     r.redirectURL,
 	}
 }
 
diff --git a/internal/oidc/authcode/authcode.go b/internal/oidc/authcode/authcode.go
index 2ee989484c8b27f036b2a8fffa4387bbc67b4003..29558e66d620c09a3e214f29507550ee57c49d4f 100644
--- a/internal/oidc/authcode/authcode.go
+++ b/internal/oidc/authcode/authcode.go
@@ -34,6 +34,7 @@ import (
 	"github.com/oidc-mytoken/server/shared/utils"
 	"github.com/oidc-mytoken/server/shared/utils/issuerUtils"
 	"github.com/oidc-mytoken/server/shared/utils/jwtutils"
+	"github.com/oidc-mytoken/server/shared/utils/ternary"
 	"github.com/oidc-mytoken/server/shared/utils/unixtime"
 )
 
@@ -103,6 +104,7 @@ func StartAuthCodeFlow(ctx *fiber.Ctx, oidcReq response.OIDCFlowRequest) *model.
 			Response: api.ErrorUnknownIssuer,
 		}
 	}
+	req.Issuer = provider.Issuer
 	exp := req.Restrictions.GetExpires()
 	if exp > 0 && exp < unixtime.Now() {
 		return &model.Response{
@@ -112,19 +114,11 @@ func StartAuthCodeFlow(ctx *fiber.Ctx, oidcReq response.OIDCFlowRequest) *model.
 	}
 
 	oState, consentCode := state.CreateState()
-	authFlowInfoO := authcodeinforepo.AuthFlowInfoOut{
-		State:                oState,
-		Issuer:               provider.Issuer,
-		Restrictions:         req.Restrictions,
-		Capabilities:         req.Capabilities,
-		SubtokenCapabilities: req.SubtokenCapabilities,
-		Name:                 req.Name,
-		Rotation:             req.Rotation,
-		ResponseType:         req.ResponseType,
-		MaxTokenLen:          req.MaxTokenLen,
-	}
 	authFlowInfo := authcodeinforepo.AuthFlowInfo{
-		AuthFlowInfoOut: authFlowInfoO,
+		AuthFlowInfoOut: authcodeinforepo.AuthFlowInfoOut{
+			State:               oState,
+			AuthCodeFlowRequest: req,
+		},
 	}
 	res := api.AuthCodeFlowResponse{
 		AuthorizationURL: utils.CombineURLPath(consentEndpoint, consentCode.String()),
@@ -273,7 +267,7 @@ func CodeExchange(
 	}
 	return &model.Response{
 		Status:   fiber.StatusSeeOther,
-		Response: "/home",
+		Response: ternary.IfNotEmptyOr(authInfo.RedirectURL, "/home"),
 		Cookies:  []*fiber.Cookie{cookie},
 	}
 }
diff --git a/internal/server/web/static/js/login.js b/internal/server/web/static/js/login.js
index 22622a92e6aedd98ce4af29c14f22108c8b81ed0..0c0abcaba1aa14dfc7e62e3ded12afff2446a61b 100644
--- a/internal/server/web/static/js/login.js
+++ b/internal/server/web/static/js/login.js
@@ -26,8 +26,10 @@ $('#login-form').on('submit', function(e){
     ]
     data['rotation'] = {
         "on_other": true,
-        "lifetime": 3600*24,
+        "lifetime": 3600 * 24,
     }
+    data['redirect_type'] = 'web';
+    data['redirect_url'] = '/home';
     data['name'] = "mytoken-web";
     storageSet("oidc_issuer", data["oidc_issuer"], true);
     data = JSON.stringify(data);
@@ -35,7 +37,7 @@ $('#login-form').on('submit', function(e){
         type: "POST",
         url: storageGet("mytoken_endpoint"),
         data: data,
-        success: function(res){
+        success: function (res) {
             window.location.href = res['authorization_url'];
         },
         dataType: "json",