diff --git a/api/api.yaml b/api/api.yaml
index 2c33ff416..407b2b260 100644
--- a/api/api.yaml
+++ b/api/api.yaml
@@ -973,6 +973,11 @@ paths:
               name: uuid
               path: github.com/google/uuid
             example: 8edd8112-c415-11ed-b036-debe37e1cbd6
+        - in: query
+          name: issuer
+          schema:
+            type: string
+
       responses:
         '200':
           description: A json to generate a QR code
@@ -1262,7 +1267,6 @@ paths:
         - Links
       parameters:
         - $ref: '#/components/parameters/pathIdentifier'
-        - $ref: '#/components/parameters/sessionID'
         - $ref: '#/components/parameters/linkID'
       requestBody:
         required: true
@@ -2202,9 +2206,6 @@ components:
         universalLink:
           type: string
           example: https://wallet.privado.id#request_uri=url
-        sessionID:
-          type: string
-          example: ab5d5dbf-aaaa-bbbb-b983-f48afea64e05
         linkDetail:
           $ref: '#/components/schemas/LinkSimple'
 
diff --git a/internal/api/api.gen.go b/internal/api/api.gen.go
index ff5a7cc91..983649571 100644
--- a/internal/api/api.gen.go
+++ b/internal/api/api.gen.go
@@ -287,7 +287,6 @@ type CredentialLinkQrCodeResponse struct {
 	Issuer        IssuerDescription `json:"issuer"`
 	LinkDetail    LinkSimple        `json:"linkDetail"`
 	QrCodeRaw     string            `json:"qrCodeRaw"`
-	SessionID     string            `json:"sessionID"`
 	UniversalLink string            `json:"universalLink"`
 }
 
@@ -686,9 +685,6 @@ type CreateLinkQrCodeCallbackTextBody = string
 
 // CreateLinkQrCodeCallbackParams defines parameters for CreateLinkQrCodeCallback.
 type CreateLinkQrCodeCallbackParams struct {
-	// SessionID Session ID e.g: 89d298fa-15a6-4a1d-ab13-d1069467eedd
-	SessionID SessionID `form:"sessionID" json:"sessionID"`
-
 	// LinkID Session ID e.g: 89d298fa-15a6-4a1d-ab13-d1069467eedd
 	LinkID LinkID `form:"linkID" json:"linkID"`
 }
@@ -762,7 +758,8 @@ type GetStateTransactionsParamsSort string
 
 // GetQrFromStoreParams defines parameters for GetQrFromStore.
 type GetQrFromStoreParams struct {
-	Id *uuid.UUID `form:"id,omitempty" json:"id,omitempty"`
+	Id     *uuid.UUID `form:"id,omitempty" json:"id,omitempty"`
+	Issuer *string    `form:"issuer,omitempty" json:"issuer,omitempty"`
 }
 
 // AuthQRCodeParams defines parameters for AuthQRCode.
@@ -1778,21 +1775,6 @@ func (siw *ServerInterfaceWrapper) CreateLinkQrCodeCallback(w http.ResponseWrite
 	// Parameter object where we will unmarshal all parameters from the context
 	var params CreateLinkQrCodeCallbackParams
 
-	// ------------- Required query parameter "sessionID" -------------
-
-	if paramValue := r.URL.Query().Get("sessionID"); paramValue != "" {
-
-	} else {
-		siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "sessionID"})
-		return
-	}
-
-	err = runtime.BindQueryParameter("form", true, true, "sessionID", r.URL.Query(), &params.SessionID)
-	if err != nil {
-		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "sessionID", Err: err})
-		return
-	}
-
 	// ------------- Required query parameter "linkID" -------------
 
 	if paramValue := r.URL.Query().Get("linkID"); paramValue != "" {
@@ -2534,6 +2516,14 @@ func (siw *ServerInterfaceWrapper) GetQrFromStore(w http.ResponseWriter, r *http
 		return
 	}
 
+	// ------------- Optional query parameter "issuer" -------------
+
+	err = runtime.BindQueryParameter("form", true, false, "issuer", r.URL.Query(), &params.Issuer)
+	if err != nil {
+		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "issuer", Err: err})
+		return
+	}
+
 	handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		siw.Handler.GetQrFromStore(w, r, params)
 	}))
diff --git a/internal/api/authentication_test.go b/internal/api/authentication_test.go
index df43feec4..e2d599f49 100644
--- a/internal/api/authentication_test.go
+++ b/internal/api/authentication_test.go
@@ -308,3 +308,18 @@ func checkQRfetchURL(t *testing.T, qrLink string) string {
 	require.NoError(t, err)
 	return fetchURL
 }
+
+func checkQRFetchURLForLinks(t *testing.T, qrLink string) string {
+	t.Helper()
+	qrURL, err := url.Parse(qrLink)
+	require.NoError(t, err)
+	assert.Equal(t, "iden3comm", qrURL.Scheme)
+	vals, err := url.ParseQuery(qrURL.RawQuery)
+	require.NoError(t, err)
+	val, found := vals["request_uri"]
+	require.True(t, found)
+	fetchURL, err := url.QueryUnescape(val[0])
+	require.NoError(t, err)
+	fetchURL = fetchURL + "&issuer=" + vals["issuer"][0]
+	return fetchURL
+}
diff --git a/internal/api/links.go b/internal/api/links.go
index 5f983d789..7f33d1030 100644
--- a/internal/api/links.go
+++ b/internal/api/links.go
@@ -92,9 +92,18 @@ func (s *Server) CreateLinkQrCodeCallback(ctx context.Context, request CreateLin
 		return CreateLinkQrCodeCallback400JSONResponse{N400JSONResponse{"Cannot proceed with empty body"}}, nil
 	}
 
-	offer, err := s.linkService.ProcessCallBack(ctx, *request.Body, request.Params.SessionID, request.Params.LinkID, s.cfg.ServerUrl)
+	issuerDID, err := w3c.ParseDID(request.Identifier)
+	if err != nil {
+		log.Error(ctx, "parsing issuer did", "err", err, "did", request.Identifier)
+		return CreateLinkQrCodeCallback400JSONResponse{N400JSONResponse{Message: "invalid issuer did"}}, nil
+	}
+
+	offer, err := s.linkService.ProcessCallBack(ctx, *issuerDID, *request.Body, request.Params.LinkID, s.cfg.ServerUrl)
 	if err != nil {
 		log.Error(ctx, "error issuing the claim", "error", err)
+		if errors.Is(err, services.ErrLinkAlreadyExpired) || errors.Is(err, services.ErrLinkMaxExceeded) || errors.Is(err, services.ErrLinkInactive) {
+			return CreateLinkQrCodeCallback400JSONResponse{N400JSONResponse{Message: "error: " + err.Error()}}, nil
+		}
 		return CreateLinkQrCodeCallback500JSONResponse{
 			N500JSONResponse{
 				Message: "error processing the callback",
@@ -192,13 +201,6 @@ func (s *Server) CreateLinkQrCode(ctx context.Context, req CreateLinkQrCodeReque
 		return CreateLinkQrCode500JSONResponse{N500JSONResponse{"Unexpected error while creating qr code"}}, nil
 	}
 
-	// Backward compatibility. If the type is raw, we return the raw qr code
-	qrCodeRaw, err := s.qrService.Find(ctx, createLinkQrCodeResponse.QrID)
-	if err != nil {
-		log.Error(ctx, "qr store. Finding qr", "err", err, "id", createLinkQrCodeResponse.QrID)
-		return CreateLinkQrCode500JSONResponse{N500JSONResponse{"error looking for qr body"}}, nil
-	}
-
 	return CreateLinkQrCode200JSONResponse{
 		Issuer: IssuerDescription{
 			DisplayName: s.cfg.IssuerName,
@@ -206,8 +208,7 @@ func (s *Server) CreateLinkQrCode(ctx context.Context, req CreateLinkQrCodeReque
 		},
 		DeepLink:      createLinkQrCodeResponse.DeepLink,
 		UniversalLink: createLinkQrCodeResponse.UniversalLink,
-		QrCodeRaw:     string(qrCodeRaw),
-		SessionID:     createLinkQrCodeResponse.SessionID,
+		QrCodeRaw:     createLinkQrCodeResponse.QrCodeRaw,
 		LinkDetail:    getLinkSimpleResponse(*createLinkQrCodeResponse.Link),
 	}, nil
 }
diff --git a/internal/api/links_test.go b/internal/api/links_test.go
index f39a2b291..f2050b42e 100644
--- a/internal/api/links_test.go
+++ b/internal/api/links_test.go
@@ -1001,7 +1001,7 @@ func TestServer_CreateLinkQRCode(t *testing.T) {
 
 				realQR := protocol.AuthorizationRequestMessage{}
 
-				qrLink := checkQRfetchURL(t, response.DeepLink)
+				qrLink := checkQRFetchURLForLinks(t, response.DeepLink)
 
 				// Let's see that universal link is correct
 				assert.Equal(t, server.cfg.UniversalLinks.BaseUrl+"#request_uri="+qrLink, response.UniversalLink)
@@ -1017,17 +1017,13 @@ func TestServer_CreateLinkQRCode(t *testing.T) {
 
 				assert.NotNil(t, realQR.Body)
 				assert.Equal(t, "authentication", realQR.Body.Reason)
-				callbackArr := strings.Split(realQR.Body.CallbackURL, "sessionID")
+				callbackArr := strings.Split(realQR.Body.CallbackURL, "linkID")
 				assert.True(t, len(callbackArr) == 2)
 				assert.Equal(t, callBack, callbackArr[0])
-				params := strings.Split(callbackArr[1], "linkID")
-				assert.True(t, len(params) == 2)
-				assert.NotNil(t, realQR.ID)
 				assert.Equal(t, "https://iden3-communication.io/authorization/1.0/request", string(realQR.Type))
 				assert.Equal(t, "application/iden3comm-plain-json", string(realQR.Typ))
 				assert.Equal(t, did.String(), realQR.From)
 				assert.NotNil(t, realQR.ThreadID)
-				assert.NotNil(t, response.SessionID)
 				assert.Equal(t, tc.expected.linkDetail.Id, response.LinkDetail.Id)
 				assert.Equal(t, tc.expected.linkDetail.SchemaType, response.LinkDetail.SchemaType)
 
diff --git a/internal/api/qrcode.go b/internal/api/qrcode.go
index ef7f8931a..3f9061242 100644
--- a/internal/api/qrcode.go
+++ b/internal/api/qrcode.go
@@ -3,6 +3,8 @@ package api
 import (
 	"context"
 
+	"github.com/iden3/go-iden3-core/v2/w3c"
+
 	"github.com/polygonid/sh-id-platform/internal/log"
 )
 
@@ -15,7 +17,25 @@ func (s *Server) GetQrFromStore(ctx context.Context, request GetQrFromStoreReque
 	body, err := s.qrService.Find(ctx, *request.Params.Id)
 	if err != nil {
 		log.Error(ctx, "qr store. Finding qr", "err", err, "id", *request.Params.Id)
-		return GetQrFromStore500JSONResponse{N500JSONResponse{"error looking for qr body"}}, nil
+
+		if request.Params.Issuer == nil {
+			return GetQrFromStore400JSONResponse{N400JSONResponse{"error looking for qr body"}}, nil
+		}
+
+		issuerDID, err := w3c.ParseDID(*request.Params.Issuer)
+		if err != nil {
+			log.Error(ctx, "parsing issuer did", "err", err, "did", *request.Params.Issuer)
+			return GetQrFromStore400JSONResponse{N400JSONResponse{"invalid issuer did"}}, nil
+		}
+
+		link, err := s.linkService.GetByID(ctx, *issuerDID, *request.Params.Id)
+
+		if link.AuthorizationRequestMessage == nil {
+			log.Error(ctx, "qr store. Finding qr", "err", err, "id", *request.Params.Id)
+			return GetQrFromStore400JSONResponse{N400JSONResponse{"error looking for qr body"}}, nil
+		}
+
+		return NewQrContentResponse(link.AuthorizationRequestMessage.Bytes), nil
 	}
 	return NewQrContentResponse(body), nil
 }
diff --git a/internal/core/domain/link.go b/internal/core/domain/link.go
index 2715a2546..8752754a1 100644
--- a/internal/core/domain/link.go
+++ b/internal/core/domain/link.go
@@ -10,6 +10,7 @@ import (
 	"github.com/iden3/go-schema-processor/v2/verifiable"
 	"github.com/iden3/iden3comm/v2"
 	"github.com/iden3/iden3comm/v2/protocol"
+	"github.com/jackc/pgtype"
 
 	"github.com/polygonid/sh-id-platform/internal/common"
 )
@@ -62,21 +63,22 @@ type LinkCoreDID w3c.DID
 
 // Link - represents a credential offer
 type Link struct {
-	ID                       uuid.UUID
-	IssuerDID                LinkCoreDID
-	CreatedAt                time.Time
-	MaxIssuance              *int
-	ValidUntil               *time.Time
-	SchemaID                 uuid.UUID
-	CredentialExpiration     *time.Time
-	CredentialSignatureProof bool
-	CredentialMTPProof       bool
-	CredentialSubject        CredentialSubject
-	Active                   bool
-	Schema                   *Schema
-	IssuedClaims             int // TODO: Give a value when link redemption is implemented
-	RefreshService           *verifiable.RefreshService
-	DisplayMethod            *verifiable.DisplayMethod
+	ID                          uuid.UUID
+	IssuerDID                   LinkCoreDID
+	CreatedAt                   time.Time
+	MaxIssuance                 *int
+	ValidUntil                  *time.Time
+	SchemaID                    uuid.UUID
+	CredentialExpiration        *time.Time
+	CredentialSignatureProof    bool
+	CredentialMTPProof          bool
+	CredentialSubject           CredentialSubject
+	Active                      bool
+	Schema                      *Schema
+	IssuedClaims                int // TODO: Give a value when link redemption is implemented
+	RefreshService              *verifiable.RefreshService
+	DisplayMethod               *verifiable.DisplayMethod
+	AuthorizationRequestMessage *pgtype.JSONB `json:"authorization_request_message"`
 }
 
 // NewLink - Constructor
diff --git a/internal/core/ports/identity_service.go b/internal/core/ports/identity_service.go
index ef55e6caa..b3372baa2 100644
--- a/internal/core/ports/identity_service.go
+++ b/internal/core/ports/identity_service.go
@@ -54,6 +54,7 @@ type IdentityService interface {
 	GetStates(ctx context.Context, issuerDID w3c.DID, filter *GetStateTransactionsRequest) ([]domain.IdentityState, uint, error)
 	CreateAuthenticationQRCode(ctx context.Context, serverURL string, issuerDID w3c.DID) (*CreateAuthenticationQRCodeResponse, error)
 	Authenticate(ctx context.Context, message string, sessionID uuid.UUID, serverURL string) (*protocol.AuthorizationResponseMessage, error)
+	AuthenticateWithRequest(ctx context.Context, sessionID *uuid.UUID, authReq protocol.AuthorizationRequestMessage, message string, serverURL string) (*protocol.AuthorizationResponseMessage, error)
 	GetFailedState(ctx context.Context, identifier w3c.DID) (*domain.IdentityState, error)
 	PublishGenesisStateToRHS(ctx context.Context, did *w3c.DID) error
 	UpdateIdentityDisplayName(ctx context.Context, did w3c.DID, displayName string) error
diff --git a/internal/core/ports/link_repository.go b/internal/core/ports/link_repository.go
index 1cff5ff2b..bd1670594 100644
--- a/internal/core/ports/link_repository.go
+++ b/internal/core/ports/link_repository.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/google/uuid"
 	"github.com/iden3/go-iden3-core/v2/w3c"
+	"github.com/iden3/iden3comm/v2/protocol"
 
 	"github.com/polygonid/sh-id-platform/internal/core/domain"
 	"github.com/polygonid/sh-id-platform/internal/db"
@@ -16,4 +17,5 @@ type LinkRepository interface {
 	GetByID(ctx context.Context, issuerID w3c.DID, id uuid.UUID) (*domain.Link, error)
 	GetAll(ctx context.Context, issuerDID w3c.DID, status LinkStatus, query *string) ([]domain.Link, error)
 	Delete(ctx context.Context, id uuid.UUID, issuerDID w3c.DID) error
+	AddAuthorizationRequest(ctx context.Context, linkID uuid.UUID, issuerDID w3c.DID, authorizationRequest *protocol.AuthorizationRequestMessage) error
 }
diff --git a/internal/core/ports/link_service.go b/internal/core/ports/link_service.go
index 2e097077d..a21553e1f 100644
--- a/internal/core/ports/link_service.go
+++ b/internal/core/ports/link_service.go
@@ -22,19 +22,19 @@ type CreateQRCodeResponse struct {
 	DeepLink      string
 	UniversalLink string
 	QrID          uuid.UUID
-	SessionID     string
+	QrCodeRaw     string
 }
 
 // LinkStatus is a Link type request. All|Active|Inactive|Exceeded
 type LinkStatus string
 
 const (
-	LinkAll          LinkStatus = "all"                                                                   // LinkAll : All links
-	LinkActive       LinkStatus = "active"                                                                // LinkActive : Active links
-	LinkInactive     LinkStatus = "inactive"                                                              // LinkInactive : Inactive links
-	LinkExceeded     LinkStatus = "exceeded"                                                              // LinkExceeded : Expired links or with more credentials issued than expected
-	AgentUrl                    = "%s/v2/agent"                                                           // AgentUrl : Agent URL
-	LinksCallbackURL            = "%s/v2/identities/%s/credentials/links/callback?sessionID=%s&linkID=%s" // LinksCallbackURL : Links callback URL
+	LinkAll          LinkStatus = "all"                                                      // LinkAll : All links
+	LinkActive       LinkStatus = "active"                                                   // LinkActive : Active links
+	LinkInactive     LinkStatus = "inactive"                                                 // LinkInactive : Inactive links
+	LinkExceeded     LinkStatus = "exceeded"                                                 // LinkExceeded : Expired links or with more credentials issued than expected
+	AgentUrl                    = "%s/v2/agent"                                              // AgentUrl : Agent URL
+	LinksCallbackURL            = "%s/v2/identities/%s/credentials/links/callback?linkID=%s" // LinksCallbackURL : Links callback URL
 )
 
 // LinkTypeReqFromString constructs a LinkStatus from a string
@@ -61,6 +61,5 @@ type LinkService interface {
 	GetAll(ctx context.Context, issuerDID w3c.DID, status LinkStatus, query *string) ([]domain.Link, error)
 	CreateQRCode(ctx context.Context, issuerDID w3c.DID, linkID uuid.UUID, serverURL string) (*CreateQRCodeResponse, error)
 	IssueOrFetchClaim(ctx context.Context, issuerDID w3c.DID, userDID w3c.DID, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error)
-	ProcessCallBack(ctx context.Context, message string, sessionID uuid.UUID, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error)
-	GetQRCode(ctx context.Context, sessionID uuid.UUID, issuerID w3c.DID, linkID uuid.UUID) (*GetQRCodeResponse, error)
+	ProcessCallBack(ctx context.Context, issuerDID w3c.DID, message string, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error)
 }
diff --git a/internal/core/ports/qrstore_service.go b/internal/core/ports/qrstore_service.go
index 4e9cf49e4..cdf7c47fd 100644
--- a/internal/core/ports/qrstore_service.go
+++ b/internal/core/ports/qrstore_service.go
@@ -5,13 +5,21 @@ import (
 	"time"
 
 	"github.com/google/uuid"
+	"github.com/iden3/go-iden3-core/v2/w3c"
 )
 
 const (
 	// QRStoreUrl is the URL to the QR store service
 	QRStoreUrl = "iden3comm://?request_uri=%s/v2/qr-store?id=%s"
+
+	// QRStoreUrlWithDID is the URL to the QR store service with the issuer DID
+	QRStoreUrlWithDID = "iden3comm://?request_uri=%s/v2/qr-store?id=%s&issuer=%s"
+
 	// UniversalLinkURL - is the URL to the Universal Link
 	UniversalLinkURL = "%s#request_uri=%s/v2/qr-store?id=%s"
+
+	// UniversalLinkURLWithDID - is the URL to the Universal Link with the issuer DID
+	UniversalLinkURLWithDID = "%s#request_uri=%s/v2/qr-store?id=%s&issuer=%s"
 )
 
 // QrStoreService is the interface that provides methods to store and retrieve the body of QR codes and to provide support
@@ -19,6 +27,6 @@ const (
 type QrStoreService interface {
 	Find(ctx context.Context, id uuid.UUID) ([]byte, error)
 	Store(ctx context.Context, qrCode []byte, ttl time.Duration) (uuid.UUID, error)
-	ToDeepLink(hostURL string, id uuid.UUID) string
-	ToUniversalLink(ULinkBaseUrl string, hostURL string, id uuid.UUID) string
+	ToDeepLink(hostURL string, id uuid.UUID, issuerDID *w3c.DID) string
+	ToUniversalLink(ULinkBaseUrl string, hostURL string, id uuid.UUID, issuerDID *w3c.DID) string
 }
diff --git a/internal/core/ports/session_repository.go b/internal/core/ports/session_repository.go
index f3ef3dad5..21f9f3822 100644
--- a/internal/core/ports/session_repository.go
+++ b/internal/core/ports/session_repository.go
@@ -4,14 +4,10 @@ import (
 	"context"
 
 	"github.com/iden3/iden3comm/v2/protocol"
-
-	link_state "github.com/polygonid/sh-id-platform/pkg/link"
 )
 
 // SessionRepository defines the interface for managing sessions
 type SessionRepository interface {
 	Get(ctx context.Context, key string) (protocol.AuthorizationRequestMessage, error)
 	Set(ctx context.Context, key string, value protocol.AuthorizationRequestMessage) error
-	SetLink(ctx context.Context, key string, value link_state.State) error
-	GetLink(ctx context.Context, key string) (link_state.State, error)
 }
diff --git a/internal/core/services/claims.go b/internal/core/services/claims.go
index f040185e1..80e3b4860 100644
--- a/internal/core/services/claims.go
+++ b/internal/core/services/claims.go
@@ -373,8 +373,8 @@ func (c *claim) GetCredentialQrCode(ctx context.Context, issID *w3c.DID, id uuid
 		return nil, err
 	}
 	return &ports.GetCredentialQrCodeResponse{
-		DeepLink:      c.qrService.ToDeepLink(hostURL, qrID),
-		UniversalLink: c.qrService.ToUniversalLink(c.cfg.BaseUrl, hostURL, qrID),
+		DeepLink:      c.qrService.ToDeepLink(hostURL, qrID, nil),
+		UniversalLink: c.qrService.ToUniversalLink(c.cfg.BaseUrl, hostURL, qrID, nil),
 		QrRaw:         string(raw),
 		SchemaType:    getCredentialType(*claim),
 		QrID:          qrID,
diff --git a/internal/core/services/identity.go b/internal/core/services/identity.go
index 930773610..073185189 100644
--- a/internal/core/services/identity.go
+++ b/internal/core/services/identity.go
@@ -472,13 +472,7 @@ func (i *identity) UpdateIdentityState(ctx context.Context, state *domain.Identi
 	return err
 }
 
-func (i *identity) Authenticate(ctx context.Context, message string, sessionID uuid.UUID, serverURL string) (*protocol.AuthorizationResponseMessage, error) {
-	authReq, err := i.sessionManager.Get(ctx, sessionID.String())
-	if err != nil {
-		log.Warn(ctx, "authentication session not found")
-		return nil, err
-	}
-
+func (i *identity) AuthenticateWithRequest(ctx context.Context, sessionID *uuid.UUID, authReq protocol.AuthorizationRequestMessage, message string, serverURL string) (*protocol.AuthorizationResponseMessage, error) {
 	arm, err := i.verifier.FullVerify(ctx, message, authReq, pubsignals.WithAcceptedStateTransitionDelay(transitionDelay))
 	if err != nil {
 		log.Error(ctx, "authentication failed", "err", err)
@@ -522,7 +516,10 @@ func (i *identity) Authenticate(ctx context.Context, message string, sessionID u
 			return err
 		}
 
-		return i.connectionsRepository.SaveUserAuthentication(ctx, i.storage.Pgx, connID, sessionID, conn.CreatedAt)
+		if sessionID == nil {
+			sessionID = common.ToPointer(uuid.New())
+		}
+		return i.connectionsRepository.SaveUserAuthentication(ctx, i.storage.Pgx, connID, *sessionID, conn.CreatedAt)
 	}); err != nil {
 		return nil, err
 	}
@@ -533,10 +530,18 @@ func (i *identity) Authenticate(ctx context.Context, message string, sessionID u
 			log.Error(ctx, "sending connection notification", "err", err.Error(), "connection", connID)
 		}
 	}
-
 	return arm, nil
 }
 
+func (i *identity) Authenticate(ctx context.Context, message string, sessionID uuid.UUID, serverURL string) (*protocol.AuthorizationResponseMessage, error) {
+	authReq, err := i.sessionManager.Get(ctx, sessionID.String())
+	if err != nil {
+		log.Warn(ctx, "authentication session not found")
+		return nil, err
+	}
+	return i.AuthenticateWithRequest(ctx, &sessionID, authReq, message, serverURL)
+}
+
 func (i *identity) CreateAuthenticationQRCode(ctx context.Context, serverURL string, issuerDID w3c.DID) (*ports.CreateAuthenticationQRCodeResponse, error) {
 	sessionID := uuid.New()
 	reqID := uuid.New().String()
@@ -566,7 +571,7 @@ func (i *identity) CreateAuthenticationQRCode(ctx context.Context, serverURL str
 		return nil, err
 	}
 	return &ports.CreateAuthenticationQRCodeResponse{
-		QRCodeURL: i.qrService.ToDeepLink(serverURL, linkID),
+		QRCodeURL: i.qrService.ToDeepLink(serverURL, linkID, nil),
 		SessionID: sessionID,
 		QrID:      linkID,
 	}, nil
diff --git a/internal/core/services/link.go b/internal/core/services/link.go
index d8fedb1a4..e684e7b73 100644
--- a/internal/core/services/link.go
+++ b/internal/core/services/link.go
@@ -23,7 +23,6 @@ import (
 	"github.com/polygonid/sh-id-platform/internal/loader"
 	"github.com/polygonid/sh-id-platform/internal/log"
 	"github.com/polygonid/sh-id-platform/internal/repositories"
-	linkState "github.com/polygonid/sh-id-platform/pkg/link"
 	"github.com/polygonid/sh-id-platform/pkg/network"
 	"github.com/polygonid/sh-id-platform/pkg/notifications"
 	"github.com/polygonid/sh-id-platform/pkg/pubsub"
@@ -166,6 +165,7 @@ func (ls *Link) Delete(ctx context.Context, id uuid.UUID, did w3c.DID) error {
 func (ls *Link) CreateQRCode(ctx context.Context, issuerDID w3c.DID, linkID uuid.UUID, serverURL string) (*ports.CreateQRCodeResponse, error) {
 	link, err := ls.GetByID(ctx, issuerDID, linkID)
 	if err != nil {
+		log.Error(ctx, "cannot fetch the link", "err", err)
 		return nil, err
 	}
 
@@ -174,42 +174,45 @@ func (ls *Link) CreateQRCode(ctx context.Context, issuerDID w3c.DID, linkID uuid
 		return nil, err
 	}
 
-	sessionID := uuid.New().String()
-	reqID := uuid.New().String()
-	qrCode := &protocol.AuthorizationRequestMessage{
-		From:     issuerDID.String(),
-		ID:       reqID,
-		ThreadID: reqID,
-		Typ:      packers.MediaTypePlainMessage,
-		Type:     protocol.AuthorizationRequestMessageType,
-		Body: protocol.AuthorizationRequestMessageBody{
-			CallbackURL: fmt.Sprintf(ports.LinksCallbackURL, serverURL, issuerDID.String(), sessionID, linkID.String()),
-			Reason:      authReason,
-			Scope:       make([]protocol.ZeroKnowledgeProofRequest, 0),
-		},
-	}
-
-	err = ls.sessionManager.Set(ctx, sessionID, *qrCode)
-	if err != nil {
-		return nil, err
-	}
-
-	raw, err := json.Marshal(qrCode)
-	if err != nil {
-		return nil, err
-	}
+	var authorizationRequestMessage *protocol.AuthorizationRequestMessage
+	var raw []byte
+	if link.AuthorizationRequestMessage == nil {
+		reqID := uuid.New().String()
+		authorizationRequestMessage = &protocol.AuthorizationRequestMessage{
+			From:     issuerDID.String(),
+			ID:       reqID,
+			ThreadID: reqID,
+			Typ:      packers.MediaTypePlainMessage,
+			Type:     protocol.AuthorizationRequestMessageType,
+			Body: protocol.AuthorizationRequestMessageBody{
+				CallbackURL: fmt.Sprintf(ports.LinksCallbackURL, serverURL, issuerDID.String(), linkID.String()),
+				Reason:      authReason,
+				Scope:       make([]protocol.ZeroKnowledgeProofRequest, 0),
+			},
+		}
+		if err := ls.linkRepository.AddAuthorizationRequest(ctx, linkID, issuerDID, authorizationRequestMessage); err != nil {
+			log.Error(ctx, "cannot add the authorization request", "err", err)
+			return nil, err
+		}
+		raw, err = json.Marshal(authorizationRequestMessage)
+		if err != nil {
+			log.Error(ctx, "cannot marshal the authorization", "err", err)
+		}
+	} else {
+		if err := json.Unmarshal(link.AuthorizationRequestMessage.Bytes, &authorizationRequestMessage); err != nil {
+			log.Error(ctx, "cannot unmarshal the authorization", "err", err)
+			return nil, err
+		}
+		raw = link.AuthorizationRequestMessage.Bytes
 
-	id, err := ls.qrService.Store(ctx, raw, DefaultQRBodyTTL)
-	if err != nil {
-		return nil, err
 	}
 
 	return &ports.CreateQRCodeResponse{
-		SessionID:     sessionID,
-		DeepLink:      ls.qrService.ToDeepLink(serverURL, id),
-		UniversalLink: ls.qrService.ToUniversalLink(ls.cfg.BaseUrl, serverURL, id),
-		QrID:          id,
+		DeepLink:      ls.qrService.ToDeepLink(serverURL, linkID, &issuerDID),
+		UniversalLink: ls.qrService.ToUniversalLink(ls.cfg.BaseUrl, serverURL, link.ID, &issuerDID),
+		QrID:          link.ID,
 		Link:          link,
+		QrCodeRaw:     string(raw),
 	}, nil
 }
 
@@ -313,8 +316,20 @@ func (ls *Link) IssueOrFetchClaim(ctx context.Context, issuerDID w3c.DID, userDI
 }
 
 // ProcessCallBack - process the callback.
-func (ls *Link) ProcessCallBack(ctx context.Context, message string, sessionID uuid.UUID, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error) {
-	arm, err := ls.identityService.Authenticate(ctx, message, sessionID, hostURL)
+func (ls *Link) ProcessCallBack(ctx context.Context, issuerID w3c.DID, message string, linkID uuid.UUID, hostURL string) (*protocol.CredentialsOfferMessage, error) {
+	link, err := ls.linkRepository.GetByID(ctx, issuerID, linkID)
+	if err != nil {
+		log.Error(ctx, "error fetching the link from the database", "err", err)
+		return nil, err
+	}
+
+	var authenticationRequest protocol.AuthorizationRequestMessage
+	if err := json.Unmarshal(link.AuthorizationRequestMessage.Bytes, &authenticationRequest); err != nil {
+		log.Error(ctx, "error unmarshaling the authorization request", "err", err)
+		return nil, err
+	}
+
+	arm, err := ls.identityService.AuthenticateWithRequest(ctx, nil, authenticationRequest, message, hostURL)
 	if err != nil {
 		log.Error(ctx, "error authenticating", "err", err.Error())
 		return nil, err
@@ -340,25 +355,6 @@ func (ls *Link) ProcessCallBack(ctx context.Context, message string, sessionID u
 	return offer, nil
 }
 
-// GetQRCode - return the link qr code.
-func (ls *Link) GetQRCode(ctx context.Context, sessionID uuid.UUID, issuerID w3c.DID, linkID uuid.UUID) (*ports.GetQRCodeResponse, error) {
-	link, err := ls.GetByID(ctx, issuerID, linkID)
-	if err != nil {
-		log.Error(ctx, "error fetching the link from the database", "err", err)
-		return nil, err
-	}
-
-	linkStateInCache, err := ls.sessionManager.GetLink(ctx, linkState.CredentialStateCacheKey(linkID.String(), sessionID.String()))
-	if err != nil {
-		log.Error(ctx, "error fetching the link state from the cache", "err", err)
-		return nil, err
-	}
-	return &ports.GetQRCodeResponse{
-		State: &linkStateInCache,
-		Link:  link,
-	}, nil
-}
-
 func (ls *Link) validate(ctx context.Context, link *domain.Link) error {
 	if link.ValidUntil != nil && time.Now().UTC().After(*link.ValidUntil) {
 		log.Debug(ctx, "cannot issue a credential for an expired link")
diff --git a/internal/core/services/qrstore.go b/internal/core/services/qrstore.go
index 0edadfa77..36bf3a741 100644
--- a/internal/core/services/qrstore.go
+++ b/internal/core/services/qrstore.go
@@ -8,6 +8,7 @@ import (
 	"time"
 
 	"github.com/google/uuid"
+	"github.com/iden3/go-iden3-core/v2/w3c"
 
 	"github.com/polygonid/sh-id-platform/internal/core/ports"
 	"github.com/polygonid/sh-id-platform/internal/log"
@@ -60,12 +61,19 @@ func (s *QrStoreService) Store(ctx context.Context, qrCode []byte, ttl time.Dura
 }
 
 // ToDeepLink constructs a deeplink that will be used to get the body of a QR code.
-func (s *QrStoreService) ToDeepLink(hostURL string, id uuid.UUID) string {
+func (s *QrStoreService) ToDeepLink(hostURL string, id uuid.UUID, issuerDID *w3c.DID) string {
+	if issuerDID != nil {
+		return fmt.Sprintf(ports.QRStoreUrlWithDID, hostURL, id.String(), issuerDID.String())
+	}
+
 	return fmt.Sprintf(ports.QRStoreUrl, hostURL, id.String())
 }
 
 // ToUniversalLink constructs a universal link
-func (s *QrStoreService) ToUniversalLink(uLinkBaseUrl string, hostURL string, id uuid.UUID) string {
+func (s *QrStoreService) ToUniversalLink(uLinkBaseUrl string, hostURL string, id uuid.UUID, issuerDID *w3c.DID) string {
+	if issuerDID != nil {
+		return fmt.Sprintf(ports.UniversalLinkURLWithDID, uLinkBaseUrl, hostURL, id.String(), issuerDID.String())
+	}
 	return fmt.Sprintf(ports.UniversalLinkURL, uLinkBaseUrl, hostURL, id.String())
 }
 
diff --git a/internal/db/schema/migrations/202409120950120_add_authorizartion_req_msg_to_links_table.sql b/internal/db/schema/migrations/202409120950120_add_authorizartion_req_msg_to_links_table.sql
new file mode 100644
index 000000000..afe5a1339
--- /dev/null
+++ b/internal/db/schema/migrations/202409120950120_add_authorizartion_req_msg_to_links_table.sql
@@ -0,0 +1,12 @@
+
+-- +goose Up
+-- +goose StatementBegin
+ALTER TABLE links
+    ADD COLUMN authorization_request_message jsonb NULL;
+-- +goose StatementEnd
+
+-- +goose Down
+-- +goose StatementBegin
+ALTER TABLE links
+DROP COLUMN authorization_request_message;
+-- +goose StatementEnd
diff --git a/internal/repositories/link.go b/internal/repositories/link.go
index a4562cd66..0e3741ce5 100644
--- a/internal/repositories/link.go
+++ b/internal/repositories/link.go
@@ -11,6 +11,7 @@ import (
 
 	"github.com/google/uuid"
 	"github.com/iden3/go-iden3-core/v2/w3c"
+	"github.com/iden3/iden3comm/v2/protocol"
 	"github.com/jackc/pgtype"
 	"github.com/jackc/pgx/v4"
 
@@ -76,6 +77,7 @@ SELECT links.id,
 	   links.refresh_service,
 	   links.display_method,
        count(claims.id) as issued_claims,
+       links.authorization_request_message,
        schemas.id as schema_id,
        schemas.issuer_id as schema_issuer_id,
        schemas.url,
@@ -107,6 +109,7 @@ GROUP BY links.id, schemas.id
 		&link.RefreshService,
 		&link.DisplayMethod,
 		&link.IssuedClaims,
+		&link.AuthorizationRequestMessage,
 		&s.ID,
 		&s.IssuerID,
 		&s.URL,
@@ -265,3 +268,9 @@ func (l link) Delete(ctx context.Context, id uuid.UUID, issuerDID w3c.DID) error
 	}
 	return nil
 }
+
+func (l link) AddAuthorizationRequest(ctx context.Context, linkID uuid.UUID, issuerDID w3c.DID, authorizationRequest *protocol.AuthorizationRequestMessage) error {
+	const sql = `UPDATE links SET authorization_request_message = $1 WHERE id = $2 AND issuer_id = $3`
+	_, err := l.conn.Pgx.Exec(ctx, sql, authorizationRequest, linkID, issuerDID.String())
+	return err
+}
diff --git a/internal/repositories/session.go b/internal/repositories/session.go
index 734b2e27f..1e23ca0f7 100644
--- a/internal/repositories/session.go
+++ b/internal/repositories/session.go
@@ -9,7 +9,6 @@ import (
 
 	"github.com/polygonid/sh-id-platform/internal/core/ports"
 	"github.com/polygonid/sh-id-platform/pkg/cache"
-	link_state "github.com/polygonid/sh-id-platform/pkg/link"
 )
 
 const (
@@ -40,17 +39,3 @@ func (c *cached) Get(ctx context.Context, key string) (protocol.AuthorizationReq
 func (c *cached) Set(ctx context.Context, key string, value protocol.AuthorizationRequestMessage) error {
 	return c.cache.Set(ctx, key, value, defaultTTL)
 }
-
-// SetLink - stores the given session information
-func (c *cached) SetLink(ctx context.Context, key string, value link_state.State) error {
-	return c.cache.Set(ctx, key, value, defaultTTL)
-}
-
-func (c *cached) GetLink(ctx context.Context, key string) (link_state.State, error) {
-	var message link_state.State
-	found := c.cache.Get(ctx, key, &message)
-	if !found {
-		return message, fmt.Errorf("link state not found")
-	}
-	return message, nil
-}