# frozen-string-literal: truerequire'jwt'moduleRodauthFeature.define(:jwt,:Jwt)dotranslatable_method:invalid_jwt_format_error_message,"invalid JWT format or claim in Authorization header"translatable_method:json_non_post_error_message,'non-POST method used in JSON API'translatable_method:json_not_accepted_error_message,'Unsupported Accept header. Must accept "application/json" or compatible content type'auth_value_method:json_accept_regexp,/(?:(?:\*|\bapplication)\/\*|\bapplication\/(?:vnd\.api\+)?json\b)/iauth_value_method:json_request_content_type_regexp,/\bapplication\/(?:vnd\.api\+)?json\b/iauth_value_method:json_response_content_type,'application/json'auth_value_method:json_response_error_status,400auth_value_method:json_response_custom_error_status?,trueauth_value_method:json_response_error_key,"error"auth_value_method:json_response_field_error_key,"field-error"auth_value_method:json_response_success_key,"success"auth_value_method:jwt_algorithm,"HS256"auth_value_method:jwt_authorization_ignore,/\A(?:Basic|Digest) /auth_value_method:jwt_authorization_remove,/\ABearer:?\s+/auth_value_method:jwt_check_accept?,trueauth_value_method:jwt_decode_opts,{}.freezeauth_value_method:jwt_session_key,nilauth_value_method:jwt_symbolize_deeply?,falsetranslatable_method:non_json_request_error_message,'Only JSON format requests are allowed'auth_value_methods(:only_json?,:jwt_secret,:use_jwt?)auth_methods(:json_request?,:jwt_session_hash,:jwt_token,:session_jwt,:set_jwt_token)auth_private_methods:json_response_bodydefsessionreturn@sessionifdefined?(@session)returnsuperunlessuse_jwt?s={}ifjwt_tokenunlesssession_data=jwt_payloadjson_response[json_response_error_key]=invalid_jwt_format_error_messageresponse.status||=json_response_error_statusresponse['Content-Type']||=json_response_content_typeresponse.write(_json_response_body(json_response))request.haltendifjwt_session_keysession_data=session_data[jwt_session_key]endifsession_dataifjwt_symbolize_deeply?s=JSON.parse(JSON.fast_generate(session_data),:symbolize_names=>true)elsifscope.opts[:sessions_convert_symbols]s=session_dataelsesession_data.each{|k,v|s[k.to_sym]=v}endendend@session=senddefclear_sessionsuperset_jwtifuse_jwt?enddefset_field_error(field,message)returnsuperunlessuse_jwt?json_response[json_response_field_error_key]=[field,message]enddefset_error_flash(message)returnsuperunlessuse_jwt?json_response[json_response_error_key]=messageenddefset_redirect_error_flash(message)returnsuperunlessuse_jwt?json_response[json_response_error_key]=messageenddefset_notice_flash(message)returnsuperunlessuse_jwt?json_response[json_response_success_key]=messageifinclude_success_messages?enddefset_notice_now_flash(message)returnsuperunlessuse_jwt?json_response[json_response_success_key]=messageifinclude_success_messages?enddefjson_request?return@json_requestifdefined?(@json_request)@json_request=request.content_type=~json_request_content_type_regexpenddefjwt_secretraiseArgumentError,"jwt_secret not set"enddefjwt_session_hashjwt_session_key?{jwt_session_key=>session}:sessionenddefsession_jwtJWT.encode(jwt_session_hash,jwt_secret,jwt_algorithm)enddefjwt_tokenreturn@jwt_tokenifdefined?(@jwt_token)if(v=request.env['HTTP_AUTHORIZATION'])&&v!~jwt_authorization_ignore@jwt_token=v.sub(jwt_authorization_remove,'')endenddefset_jwt_token(token)response.headers['Authorization']=tokenenddefuse_jwt?jwt_token||only_json?||json_request?enddefvalid_jwt?!!(jwt_token&&jwt_payload)enddefview(page,title)returnsuperunlessuse_jwt?return_json_responseendprivatedefcheck_csrf?returnfalseifuse_jwt?superenddefbefore_rodauthifjson_request?ifjwt_check_accept?&&(accept=request.env['HTTP_ACCEPT'])&&accept!~json_accept_regexpresponse.status=406json_response[json_response_error_key]=json_not_accepted_error_messageresponse['Content-Type']||=json_response_content_typeresponse.write(_json_response_body(json_response))request.haltendunlessrequest.post?response.status=405response.headers['Allow']='POST'json_response[json_response_error_key]=json_non_post_error_messagereturn_json_responseendelsifonly_json?response.status=json_response_error_statusresponse.writenon_json_request_error_messagerequest.haltendsuperenddefbefore_view_recovery_codessuperifdefined?(super)ifuse_jwt?json_response[:codes]=recovery_codesjson_response[json_response_success_key]||=""ifinclude_success_messages?endenddefbefore_webauthn_setup_routesuperifdefined?(super)ifuse_jwt?&&!param_or_nil(webauthn_setup_param)cred=new_webauthn_credentialjson_response[webauthn_setup_param]=cred.as_jsonjson_response[webauthn_setup_challenge_param]=cred.challengejson_response[webauthn_setup_challenge_hmac_param]=compute_hmac(cred.challenge)endenddefbefore_webauthn_auth_routesuperifdefined?(super)ifuse_jwt?&&!param_or_nil(webauthn_auth_param)cred=webauth_credential_options_for_getjson_response[webauthn_auth_param]=cred.as_jsonjson_response[webauthn_auth_challenge_param]=cred.challengejson_response[webauthn_auth_challenge_hmac_param]=compute_hmac(cred.challenge)endenddefbefore_webauthn_login_routesuperifdefined?(super)ifuse_jwt?&&!param_or_nil(webauthn_auth_param)&&account_from_login(param(login_param))cred=webauth_credential_options_for_getjson_response[webauthn_auth_param]=cred.as_jsonjson_response[webauthn_auth_challenge_param]=cred.challengejson_response[webauthn_auth_challenge_hmac_param]=compute_hmac(cred.challenge)endenddefbefore_webauthn_remove_routesuperifdefined?(super)ifuse_jwt?&&!param_or_nil(webauthn_remove_param)json_response[webauthn_remove_param]=account_webauthn_usageendenddefbefore_otp_setup_routesuperifdefined?(super)ifuse_jwt?&&otp_keys_use_hmac?&&!param_or_nil(otp_setup_raw_param)_otp_tmp_key(otp_new_secret)json_response[otp_setup_param]=otp_user_keyjson_response[otp_setup_raw_param]=otp_keyendenddefjwt_payloadreturn@jwt_payloadifdefined?(@jwt_payload)@jwt_payload=JWT.decode(jwt_token,jwt_secret,true,jwt_decode_opts.merge(:algorithm=>jwt_algorithm))[0]rescueJWT::DecodeError@jwt_payload=falseenddefredirect(_)returnsuperunlessuse_jwt?return_json_responseenddefinclude_success_messages?!json_response_success_key.nil?enddefset_session_value(key,value)superset_jwtifuse_jwt?valueenddefremove_session_value(key)value=superset_jwtifuse_jwt?valueenddefjson_response@json_response||={}enddef_json_response_body(hash)request.send(:convert_to_json,hash)enddefreturn_json_responseresponse.status||=json_response_error_statusifjson_response[json_response_error_key]set_jwtresponse['Content-Type']||=json_response_content_typeresponse.write(_json_response_body(json_response))request.haltenddefset_jwtset_jwt_token(session_jwt)enddefset_redirect_error_status(status)ifuse_jwt?&&json_response_custom_error_status?response.status=statusendenddefset_response_error_status(status)ifuse_jwt?&&!json_response_custom_error_status?status=json_response_error_statusendsuperendendend