Skip to content

Commit

Permalink
fix: make device_challenge unique
Browse files Browse the repository at this point in the history
  • Loading branch information
nsklikas committed Jan 27, 2025
1 parent 09c513c commit 9e2e241
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 8 deletions.
67 changes: 67 additions & 0 deletions oauth2/oauth2_device_code_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,73 @@ func TestDeviceCodeWithDefaultStrategy(t *testing.T) {
require.NoError(t, err)
require.Equal(t, loginFlowResp2.StatusCode, http.StatusBadRequest)
})
t.Run("case=cannot reuse device_challenge", func(t *testing.T) {
var deviceChallenge string
c, conf := newDeviceClient(t, reg)
testhelpers.NewDeviceLoginConsentUI(t, reg.Config(),
func(w http.ResponseWriter, r *http.Request) {
userCode := r.URL.Query().Get("user_code")
payload := hydra.AcceptDeviceUserCodeRequest{
UserCode: &userCode,
}

if deviceChallenge == "" {
deviceChallenge = r.URL.Query().Get("device_challenge")
}
v, _, err := adminClient.OAuth2API.AcceptUserCodeRequest(context.Background()).
DeviceChallenge(deviceChallenge).
AcceptDeviceUserCodeRequest(payload).
Execute()
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
require.NoError(t, err)
require.NotEmpty(t, v.RedirectTo)
http.Redirect(w, r, v.RedirectTo, http.StatusFound)
},
acceptLoginHandler(t, c, subject, conf.Scopes, nil),
acceptConsentHandler(t, c, subject, conf.Scopes, nil),
)

resp, err := getDeviceCode(t, conf, nil)
require.NoError(t, err)
require.NotEmpty(t, resp.DeviceCode)
require.NotEmpty(t, resp.UserCode)

hc := testhelpers.NewEmptyJarClient(t)
loginFlowResp := acceptUserCode(t, conf, hc, resp)
require.NoError(t, err)
require.Contains(t, reg.Config().DeviceDoneURL(ctx).String(), loginFlowResp.Request.URL.Path, "did not end up in post device URL")
require.Equal(t, loginFlowResp.Request.URL.Query().Get("client_id"), conf.ClientID)

require.NotNil(t, loginFlowResp)
token, err := conf.DeviceAccessToken(context.Background(), resp)
iat := time.Now()
require.NoError(t, err)

introspectAccessToken(t, conf, token, subject)
assertIDToken(t, token, conf, subject, nonce, iat.Add(reg.Config().GetIDTokenLifespan(ctx)))
assertRefreshToken(t, token, conf, iat.Add(reg.Config().GetRefreshTokenLifespan(ctx)))

resp2, err := getDeviceCode(t, conf, nil)
require.NoError(t, err)
require.NotEmpty(t, resp2.DeviceCode)
require.NotEmpty(t, resp2.UserCode)

payload := hydra.AcceptDeviceUserCodeRequest{
UserCode: &resp2.UserCode,
}

acceptResp, _, err := adminClient.OAuth2API.AcceptUserCodeRequest(context.Background()).
DeviceChallenge(deviceChallenge).
AcceptDeviceUserCodeRequest(payload).
Execute()

loginFlowResp2, err := hc.Get(acceptResp.RedirectTo)
require.NoError(t, err)
require.Equal(t, http.StatusForbidden, loginFlowResp2.StatusCode)
})
}

func newDeviceClient(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS hydra_oauth2_device_auth_codes
CREATE INDEX hydra_oauth2_device_auth_codes_request_id_idx ON hydra_oauth2_device_auth_codes (request_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_client_id_idx ON hydra_oauth2_device_auth_codes (client_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_challenge_id_idx ON hydra_oauth2_device_auth_codes (challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (user_code_signature, nid);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (nid, user_code_signature);

ALTER TABLE hydra_oauth2_flow ADD COLUMN device_challenge_id VARCHAR(255) NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_code_request_id VARCHAR(255) NULL;
Expand All @@ -40,7 +40,7 @@ ALTER TABLE hydra_oauth2_flow ADD COLUMN device_was_used BOOL NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_handled_at TIMESTAMP NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_error TEXT NULL;

CREATE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);

ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_id_token_lifespan BIGINT NULL DEFAULT NULL;
ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_access_token_lifespan BIGINT NULL DEFAULT NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS hydra_oauth2_device_auth_codes
CREATE INDEX hydra_oauth2_device_auth_codes_request_id_idx ON hydra_oauth2_device_auth_codes (request_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_client_id_idx ON hydra_oauth2_device_auth_codes (client_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_challenge_id_idx ON hydra_oauth2_device_auth_codes (challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (user_code_signature, nid);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (nid, user_code_signature);

ALTER TABLE hydra_oauth2_flow ADD COLUMN device_challenge_id VARCHAR(255) NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_code_request_id VARCHAR(255) NULL;
Expand All @@ -40,7 +40,7 @@ ALTER TABLE hydra_oauth2_flow ADD COLUMN device_was_used BOOL NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_handled_at TIMESTAMP NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_error TEXT NULL;

CREATE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);

ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_id_token_lifespan BIGINT NULL DEFAULT NULL;
ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_access_token_lifespan BIGINT NULL DEFAULT NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS hydra_oauth2_device_auth_codes
CREATE INDEX hydra_oauth2_device_auth_codes_request_id_idx ON hydra_oauth2_device_auth_codes (request_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_client_id_idx ON hydra_oauth2_device_auth_codes (client_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_challenge_id_idx ON hydra_oauth2_device_auth_codes (challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (user_code_signature, nid);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (nid, user_code_signature);

ALTER TABLE hydra_oauth2_flow ADD COLUMN device_challenge_id VARCHAR(255) NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_code_request_id VARCHAR(255) NULL;
Expand All @@ -40,7 +40,7 @@ ALTER TABLE hydra_oauth2_flow ADD COLUMN device_was_used BOOLEAN NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_handled_at TIMESTAMP NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_error TEXT NULL;

CREATE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);

ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_id_token_lifespan BIGINT NULL DEFAULT NULL;
ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_access_token_lifespan BIGINT NULL DEFAULT NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ CREATE TABLE IF NOT EXISTS hydra_oauth2_device_auth_codes
CREATE INDEX hydra_oauth2_device_auth_codes_request_id_idx ON hydra_oauth2_device_auth_codes (request_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_client_id_idx ON hydra_oauth2_device_auth_codes (client_id, nid);
CREATE INDEX hydra_oauth2_device_auth_codes_challenge_id_idx ON hydra_oauth2_device_auth_codes (challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (user_code_signature, nid);
CREATE UNIQUE INDEX hydra_oauth2_device_auth_codes_user_code_signature_idx ON hydra_oauth2_device_auth_codes (nid, user_code_signature);

ALTER TABLE hydra_oauth2_flow ADD COLUMN device_challenge_id VARCHAR(255) NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_code_request_id VARCHAR(255) NULL;
Expand All @@ -35,7 +35,7 @@ ALTER TABLE hydra_oauth2_flow ADD COLUMN device_was_used BOOLEAN NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_handled_at TIMESTAMP NULL;
ALTER TABLE hydra_oauth2_flow ADD COLUMN device_error TEXT NULL;

CREATE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);
CREATE UNIQUE INDEX hydra_oauth2_flow_device_challenge_idx ON hydra_oauth2_flow (device_challenge_id);

ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_id_token_lifespan BIGINT NULL DEFAULT NULL;
ALTER TABLE hydra_client ADD COLUMN device_authorization_grant_access_token_lifespan BIGINT NULL DEFAULT NULL;
Expand Down

0 comments on commit 9e2e241

Please sign in to comment.